|
Archives
D Programming
digitalmars.D
digitalmars.D.bugs
digitalmars.D.dtl
digitalmars.D.ide
digitalmars.D.dwt
digitalmars.D.announce
digitalmars.D.learn
digitalmars.D.debugger
D.gnu
D
C/C++ Programming
c++
c++.announce
c++.atl
c++.beta
c++.chat
c++.command-line
c++.dos
c++.dos.16-bits
c++.dos.32-bits
c++.idde
c++.mfc
c++.rtl
c++.stl
c++.stl.hp
c++.stl.port
c++.stl.sgi
c++.stlsoft
c++.windows
c++.windows.16-bits
c++.windows.32-bits
c++.wxwindows
digitalmars.empire
digitalmars.DMDScript
electronics
|
digitalmars.D - Re: Function calls
Andrei Alexandrescu Wrote:
Michiel Helvensteijn wrote:
Andrei Alexandrescu wrote:
foreach (line; stdin.byLine()) { ... }
vs.
foreach (line; stdin.byLine) { ... }
How do I choose?
-Steve
byLine() is a function. It changes the state of stdin. Calling it
consecutively will in general result in different return values. If there
were two guys: stdin.currentLine (property) and stdin.nextLine(), it would
be a different story.
No no no. byLine returns a struct, it does not modify stdin. Operating on the
struct modifies stdin, but that is outside the call to the property getter.
Look at it this way (although this is not the only way to look at it), could
byLine be a field inside stdin? It could. You could store a copy of what
byLine returns inside stdin, and people could just access it.
A property should act very much like a field. The advantages of properties
are that they can be derived (not have a one-to-one relation with a storage
location) or can do some clever caching/memoizing/logging.
I agree, but I'll also note that I got contradictory opinions from
different supporters of property. So now it looks all the more like a
judgment call, which is exactly what I was worried in the first place.
There are some cases that are judgement calls and some that are obvious.
byLine is obvious.
The difference is that the *author* is making the judgement call, not the
*user*. The difference is important, because when a user complains that your
property is doing things a property shouldn't, and then you realize the
"property" in question isn't even a property at all, your only solution (with
the non-attributed system) is to tell the user not to use it that way. There
is no way to get him to stop, or to get other users to stop. You have lost
control over the semantic meaning of your function, even though you defined it
and documented it.
And yes, this did actually happen to me.
Omitting parentheses on an action just because you can is stupid. It
actually makes the language less readable and less predictable. And all
that for saving two keystrokes.
I found my code to be more readable and just as predictable with the
current rule. And it's not about two keystrokes, it's about persistent
and ubiquitous syntactic noise.
Gosh, property does suck. I was afraid that'd be true.
This is your opinion when reading *your* code. It doesn't suck if you value
being able to read code written by *others*.
-Steve
On 01/29/2010 05:20 AM, Steven Schveighoffer wrote:
Look at it this way (although this is not the only way to look at it), could
byLine be a field inside stdin? It could. You could store a copy of what
byLine returns inside stdin, and people could just access it.
byLine modifies stdin. If you do this:
auto a = stdin.byLine;
You consume a line off stdin.
There are some cases that are judgement calls and some that are obvious.
byLine is obvious.
Apparently not.
The difference is that the *author* is making the judgement call, not the
*user*. The difference is important, because when a user complains that your
property is doing things a property shouldn't, and then you realize the
"property" in question isn't even a property at all, your only solution (with
the non-attributed system) is to tell the user not to use it that way. There
is no way to get him to stop, or to get other users to stop. You have lost
control over the semantic meaning of your function, even though you defined it
and documented it.
And yes, this did actually happen to me.
Sounds like a naming issue to me. :)
On Fri, 29 Jan 2010 06:16:15 -0500, Pelle MÃ¥nsson
<pelle.mansson gmail.com> wrote:
On 01/29/2010 05:20 AM, Steven Schveighoffer wrote:
Look at it this way (although this is not the only way to look at it),
could byLine be a field inside stdin? It could. You could store a
copy of what byLine returns inside stdin, and people could just access
it.
byLine modifies stdin. If you do this:
auto a = stdin.byLine;
You consume a line off stdin.
That's a deficiency in the design of byLine. It's a range that "primes"
itself with a line of text. The fact that you can enter the line above
and just throw away the data seems error prone to me. When would you ever
use that "feature"? In practice, it doesn't matter, because the only
purpose to fetch the byLine struct is to iterate data from stdin.
The design could be fixed with a boolean isPrimed that is unset on the
first call to front. But like I said, it doesn't matter in the long run,
since nobody ever fetches byLine without using it.
I find that the shoehorning of an input range onto a stream is always
going to have this problem, so there's not much we can do about it. It
doesn't change the concept that byLine is a property. I find streams much
better suited to opApply, but I've already had that unsuccessful battle,
and I don't want to have it again.
There are some cases that are judgement calls and some that are
obvious. byLine is obvious.
Apparently not.
I don't see why you think it's not a property. It fetches a range from
stdin, there is no other purpose. If you think byLine's purpose is to
throw away a line of text, I think first that you are now attaching
unintended semantic meaning to it (exactly what properties are meant to
prevent) and second, I'd consider it to be a poorly named function. I
guess someone should complain that it's not called popLine(), because as a
function, that's what it does.
The difference is that the *author* is making the judgement call, not
the *user*. The difference is important, because when a user complains
that your property is doing things a property shouldn't, and then you
realize the "property" in question isn't even a property at all, your
only solution (with the non-attributed system) is to tell the user not
to use it that way. There is no way to get him to stop, or to get
other users to stop. You have lost control over the semantic meaning
of your function, even though you defined it and documented it.
And yes, this did actually happen to me.
Sounds like a naming issue to me. :)
You be the judge: http://www.dsource.org/projects/tango/ticket/1184
I find the resulting workaround very unsavory.
-Steve
On 01/29/2010 02:01 PM, Steven Schveighoffer wrote:
That's a deficiency in the design of byLine. It's a range that "primes"
itself with a line of text. The fact that you can enter the line above
and just throw away the data seems error prone to me. When would you
ever use that "feature"? In practice, it doesn't matter, because the
only purpose to fetch the byLine struct is to iterate data from stdin.
The design could be fixed with a boolean isPrimed that is unset on the
first call to front. But like I said, it doesn't matter in the long run,
since nobody ever fetches byLine without using it.
I find that the shoehorning of an input range onto a stream is always
going to have this problem, so there's not much we can do about it. It
doesn't change the concept that byLine is a property. I find streams
much better suited to opApply, but I've already had that unsuccessful
battle, and I don't want to have it again.
So byLine should be a property when implemented as a range, and a
function when implemented as an opApply based loop?
I feel that is a problem.
You be the judge: http://www.dsource.org/projects/tango/ticket/1184
I find the resulting workaround very unsavory.
-Steve
That's the assignment syntax, which I do agree is weird. Sorry if I was
unclear. This is what I thought property was for.
It has, however, nothing to do with the omitting of the ().
On 01/29/2010 07:10 PM, Steven Schveighoffer wrote:
Note in the anecdote above, both users would have
been satisfied if you could *only* call empty without parentheses.
That's a good point. The writeln = 3; is also a good point. :)
What I'm trying to defend is the ability to call non-property functions
without the parens.
I find this:
array.stable_sort;
file.detach;
range.popFront;
to look less noisy, clearer and just plain sexier than the respective
versions with the parens.
On 01/29/2010 08:07 PM, Steven Schveighoffer wrote:
On Fri, 29 Jan 2010 13:43:50 -0500, Pelle MÃ¥nsson
<pelle.mansson gmail.com> wrote:
On 01/29/2010 07:10 PM, Steven Schveighoffer wrote:
Note in the anecdote above, both users would have
been satisfied if you could *only* call empty without parentheses.
That's a good point. The writeln = 3; is also a good point. :)
What I'm trying to defend is the ability to call non-property
functions without the parens.
I find this:
array.stable_sort;
file.detach;
range.popFront;
to look less noisy, clearer and just plain sexier than the respective
versions with the parens.
You've cited three functions where the function names cannot be
misinterpreted as properties. This is not the case for all function
names. If you wish to have a way to specify a function can be called
either way, then I think you also need a way to specify that a function
can only be called with parentheses.
I don't disagree that the above is unambiguous, but there are examples
where it is ambiguous.
f.read;
does this mean read f, or is it an accidental noop fetching a property
indicating f is read?
Requiring parentheses also allows you to force meanings where they would
otherwise be interpreted as properties:
f.next();
Looks like it advances f, even though next isn't a verb. Without the
parentheses, it looks like a noop access of a property.
I disagree, it doesn't look like it advances. With the parens, it just
looks like a java-style get-function. To me, at least.
I'm not too concerned with requiring () on your examples because it's
inconsequential to me -- having parentheses isn't *less* clear than not
having them. I don't mind if you wish to allow these calls without
parens, but there has to still be a way to force the parens.
-Steve
I disagree. I understand that in some cases we would not want to permit
calling with parenthesis, and that calling as assignment is sometimes
less than ideal. I do not, however, see any reason to allow forcing of
parenthesis for regular functions.
Steven Schveighoffer wrote:
On Fri, 29 Jan 2010 13:43:50 -0500, Pelle MÃ¥nsson
<pelle.mansson gmail.com> wrote:
On 01/29/2010 07:10 PM, Steven Schveighoffer wrote:
Note in the anecdote above, both users would have
been satisfied if you could *only* call empty without parentheses.
That's a good point. The writeln = 3; is also a good point. :)
What I'm trying to defend is the ability to call non-property
functions without the parens.
I find this:
array.stable_sort;
file.detach;
range.popFront;
to look less noisy, clearer and just plain sexier than the respective
versions with the parens.
You've cited three functions where the function names cannot be
misinterpreted as properties. This is not the case for all function
names. If you wish to have a way to specify a function can be called
either way, then I think you also need a way to specify that a function
can only be called with parentheses.
I don't disagree that the above is unambiguous, but there are examples
where it is ambiguous.
f.read;
does this mean read f, or is it an accidental noop fetching a property
indicating f is read?
"Rules are not meant to be followed robotically."
Sorry I couldn't abstain :o).
Requiring parentheses also allows you to force meanings where they would
otherwise be interpreted as properties:
f.next();
Looks like it advances f, even though next isn't a verb. Without the
parentheses, it looks like a noop access of a property.
I'm not too concerned with requiring () on your examples because it's
inconsequential to me -- having parentheses isn't *less* clear than not
having them. I don't mind if you wish to allow these calls without
parens, but there has to still be a way to force the parens.
-Steve
Ok how about this: if just calling the thing changes the parent, it
can't be a property. Guess I could live with that.
Andrei
On 2010-01-29 15:02:13 -0500, Andrei Alexandrescu
<SeeWebsiteForEmail erdani.org> said:
Ok how about this: if just calling the thing changes the parent, it
can't be a property. Guess I could live with that.
Hopefully that rule will only apply to the getter. :-)
--
Michel Fortin
michel.fortin michelf.com
http://michelf.com/
"Pelle Månsson" <pelle.mansson gmail.com> wrote in message
news:hjv9sf$1n5o$1 digitalmars.com...
On 01/29/2010 07:10 PM, Steven Schveighoffer wrote:
Note in the anecdote above, both users would have
been satisfied if you could *only* call empty without parentheses.
That's a good point. The writeln = 3; is also a good point. :)
What I'm trying to defend is the ability to call non-property functions
without the parens.
I find this:
array.stable_sort;
file.detach;
range.popFront;
to look less noisy, clearer and just plain sexier than the respective
versions with the parens.
To me, at a glance, it looks like a series of no-ops. Like "x; y; z;". Only
upon closer inspection of the names does it become apperent that functions
are actually being called.
Nick Sabalausky wrote:
"Pelle Månsson" <pelle.mansson gmail.com> wrote in message
news:hjv9sf$1n5o$1 digitalmars.com...
On 01/29/2010 07:10 PM, Steven Schveighoffer wrote:
Note in the anecdote above, both users would have
been satisfied if you could *only* call empty without parentheses.
What I'm trying to defend is the ability to call non-property functions
without the parens.
I find this:
array.stable_sort;
file.detach;
range.popFront;
to look less noisy, clearer and just plain sexier than the respective
versions with the parens.
To me, at a glance, it looks like a series of no-ops. Like "x; y; z;". Only
upon closer inspection of the names does it become apperent that functions
are actually being called.
.reverse and .sort MUST be renamed. (Removal would be an acceptable form
of renaming IMHO).
== Quote from Don (nospam nospam.com)'s article
Nick Sabalausky wrote:
"Pelle Månsson" <pelle.mansson gmail.com> wrote in message
news:hjv9sf$1n5o$1 digitalmars.com...
On 01/29/2010 07:10 PM, Steven Schveighoffer wrote:
Note in the anecdote above, both users would have
been satisfied if you could *only* call empty without parentheses.
What I'm trying to defend is the ability to call non-property functions
without the parens.
I find this:
array.stable_sort;
file.detach;
range.popFront;
to look less noisy, clearer and just plain sexier than the respective
versions with the parens.
To me, at a glance, it looks like a series of no-ops. Like "x; y; z;". Only
upon closer inspection of the names does it become apperent that functions
are actually being called.
.reverse and .sort MUST be renamed. (Removal would be an acceptable form
of renaming IMHO).
Yea, can anyone even come up with a good Devil's Advocate argument in favor of
leaving these in? The best one I can think of is that, since arrays in D are
builtin, the basic functionality for them should also be builtin so they feel
"first-class". This is a pretty weak argument. The builtins made sense early
on,
but now they are slow, inflexible and not substantially easier to use than the
std.algorithm functions.
dsimcha:
Yea, can anyone even come up with a good Devil's Advocate argument in favor of
leaving these in? The best one I can think of is that, since arrays in D are
builtin, the basic functionality for them should also be builtin so they feel
"first-class". This is a pretty weak argument. The builtins made sense early
on,
but now they are slow, inflexible and not substantially easier to use than the
std.algorithm functions.
I don't know. The built-in sort is certified broken, very slow, and too much
rigid. But I like the idea of a language that has built-in some very common
operations, especially if it already has built-in data structures (like dynamic
arrays and associative arrays. Associative arrays are a complex data structure).
The good thing of the built in sort is that if you have to sort small groups of
many different types of data, you don't need to import algorithms and your
binary doesn't inflate because of all those different instances of the sort
templated function.
In the end I think that:
- The sort method from the dynamic arrays can be removed;
- The reverse method can be kept;
- More useful methods can be added to the associative arrays, I have written
about this in the past few times.
Bye,
bearophile
On Fri, 29 Jan 2010 12:42:57 -0500, Pelle MÃ¥nsson
<pelle.mansson gmail.com> wrote:
On 01/29/2010 02:01 PM, Steven Schveighoffer wrote:
That's a deficiency in the design of byLine. It's a range that "primes"
itself with a line of text. The fact that you can enter the line above
and just throw away the data seems error prone to me. When would you
ever use that "feature"? In practice, it doesn't matter, because the
only purpose to fetch the byLine struct is to iterate data from stdin.
The design could be fixed with a boolean isPrimed that is unset on the
first call to front. But like I said, it doesn't matter in the long run,
since nobody ever fetches byLine without using it.
I find that the shoehorning of an input range onto a stream is always
going to have this problem, so there's not much we can do about it. It
doesn't change the concept that byLine is a property. I find streams
much better suited to opApply, but I've already had that unsuccessful
battle, and I don't want to have it again.
So byLine should be a property when implemented as a range, and a
function when implemented as an opApply based loop?
I meant byLine should return a struct that implements opApply. If it is a
function then you have to pass the address to foreach, which is a little
awkward.
You be the judge: http://www.dsource.org/projects/tango/ticket/1184
I find the resulting workaround very unsavory.
-Steve
That's the assignment syntax, which I do agree is weird. Sorry if I was
unclear. This is what I thought property was for.
It has, however, nothing to do with the omitting of the ().
No, but it is an example of someone misinterpreting the meaning of a
function because the compiler accepted his syntax. Yes, the assignment
rewrite is more troublesome than the getter, but being able to force
someone to omit the parentheses has its advantages:
user1: When I call range.empty(), it doesn't clear the range
developer: Hm.. empty is not an action, its a property. Maybe I'll fix
it by changing it to isEmpty to make it clear.
user1: great idea! that's much clearer.
....
user2: Why did you name it isEmpty, isn't the 'is' redundant since this
looks perfectly normal? if(r.empty)
developer: *sigh*
This is the problem I ran into. Because so much meaning is attached to
the () by humans, you must resort to naming conventions to make the
intentions clear, then point out the reasons for not using a better name
to future complainers. Note in the anecdote above, both users would have
been satisfied if you could *only* call empty without parentheses.
The no-parens property requirement has nothing to do with compiler
interpretation or functionality and everything to do with human
interpretation. It's all about what does the call *look* like it's doing
as opposed to what it actually does. By enforcing the removal of
parentheses, most normal users don't have to read the docs or look at
anything else. It just works the way it's supposed to work, and looks
like it does that. This doesn't make every single case clear, nor does it
install automatic wisdom in all developers to be able to invent intuitive
names. What it does is make it *possible* for you to invent intuitive
names that retain their meaning and are succinct. I don't know about you,
but using libraries with intuitive, consistent, and succinct terminology
is really much more enjoyable than ones with inconsistent or overly
verbose terminology.
The other benefit is it makes calling delegate properties less ugly and
more consistent with analogous fields.
-Steve
On Fri, 29 Jan 2010 13:43:50 -0500, Pelle MÃ¥nsson
<pelle.mansson gmail.com> wrote:
On 01/29/2010 07:10 PM, Steven Schveighoffer wrote:
Note in the anecdote above, both users would have
been satisfied if you could *only* call empty without parentheses.
That's a good point. The writeln = 3; is also a good point. :)
What I'm trying to defend is the ability to call non-property functions
without the parens.
I find this:
array.stable_sort;
file.detach;
range.popFront;
to look less noisy, clearer and just plain sexier than the respective
versions with the parens.
You've cited three functions where the function names cannot be
misinterpreted as properties. This is not the case for all function
names. If you wish to have a way to specify a function can be called
either way, then I think you also need a way to specify that a function
can only be called with parentheses.
I don't disagree that the above is unambiguous, but there are examples
where it is ambiguous.
f.read;
does this mean read f, or is it an accidental noop fetching a property
indicating f is read?
Requiring parentheses also allows you to force meanings where they would
otherwise be interpreted as properties:
f.next();
Looks like it advances f, even though next isn't a verb. Without the
parentheses, it looks like a noop access of a property.
I'm not too concerned with requiring () on your examples because it's
inconsequential to me -- having parentheses isn't *less* clear than not
having them. I don't mind if you wish to allow these calls without
parens, but there has to still be a way to force the parens.
-Steve
On Fri, 29 Jan 2010 14:23:55 -0500, Pelle MÃ¥nsson
<pelle.mansson gmail.com> wrote:
On 01/29/2010 08:07 PM, Steven Schveighoffer wrote:
f.next();
Looks like it advances f, even though next isn't a verb. Without the
parentheses, it looks like a noop access of a property.
I disagree, it doesn't look like it advances. With the parens, it just
looks like a java-style get-function. To me, at least.
If this were Java, I'd agree with you :) But even on Java, it would have
to be getNext().
I'm not too concerned with requiring () on your examples because it's
inconsequential to me -- having parentheses isn't *less* clear than not
having them. I don't mind if you wish to allow these calls without
parens, but there has to still be a way to force the parens.
I disagree. I understand that in some cases we would not want to permit
calling with parenthesis, and that calling as assignment is sometimes
less than ideal. I do not, however, see any reason to allow forcing of
parenthesis for regular functions.
I guess D can't please everybody all the time. Oh well.
-Steve
On Fri, Jan 29, 2010 at 12:02 PM, Andrei Alexandrescu
<SeeWebsiteForEmail erdani.org> wrote:
Steven Schveighoffer wrote:
On Fri, 29 Jan 2010 13:43:50 -0500, Pelle M=E5nsson
<pelle.mansson gmail.com> wrote:
On 01/29/2010 07:10 PM, Steven Schveighoffer wrote:
Note in the anecdote above, both users would have
been satisfied if you could *only* call empty without parentheses.
That's a good point. The writeln =3D 3; is also a good point. :)
What I'm trying to defend is the ability to call non-property functions
without the parens.
I find this:
array.stable_sort;
file.detach;
range.popFront;
to look less noisy, clearer and just plain sexier than the respective
versions with the parens.
You've cited three functions where the function names cannot be
misinterpreted as properties. =A0This is not the case for all function n=
=A0If you wish to have a way to specify a function can be called either =
then I think you also need a way to specify that a function can only be
called with parentheses.
I don't disagree that the above is unambiguous, but there are examples
where it is ambiguous.
f.read;
does this mean read f, or is it an accidental noop fetching a property
indicating f is read?
"Rules are not meant to be followed robotically."
Sorry I couldn't abstain :o).
Requiring parentheses also allows you to force meanings where they would
otherwise be interpreted as properties:
f.next();
Looks like it advances f, even though next isn't a verb. =A0Without the
parentheses, it looks like a noop access of a property.
I'm not too concerned with requiring () on your examples because it's
inconsequential to me -- having parentheses isn't *less* clear than not
having them. =A0I don't mind if you wish to allow these calls without pa=
but there has to still be a way to force the parens.
-Steve
Ok how about this: if just calling the thing changes the parent, it can't=
a property. Guess I could live with that.
Should be "if calling the thing changes the parent in an outwardly
visible way". Doing refcounting or caching mutations under the hood
should be ok.
--bb
On 29.01.2010 05:20, Steven Schveighoffer wrote:
Andrei Alexandrescu Wrote:
Michiel Helvensteijn wrote:
> Andrei Alexandrescu wrote:
>
>>>> foreach (line; stdin.byLine()) { ... }
>>>>
>>>> vs.
>>>>
>>>> foreach (line; stdin.byLine) { ... }
>>>>
>>>> How do I choose?
>>> byLine is a property. It is fetching a range on stdin.
>>>
>>> -Steve
>> Damn. I was sure the answer will be different.
>
> byLine() is a function. It changes the state of stdin. Calling it
> consecutively will in general result in different return values. If there
> were two guys: stdin.currentLine (property) and stdin.nextLine(), it would
> be a different story.
No no no. byLine returns a struct, it does not modify stdin. Operating on
the struct modifies stdin, but that is outside the call to the property getter.
Look at it this way (although this is not the only way to look at it), could
byLine be a field inside stdin? It could. You could store a copy of what
byLine returns inside stdin, and people could just access it.
Before more time is wasted in this discussion, I would like to point out
that byLine does actually have two arguments. I wrote a post about
byLine yesterday, but noone seems to have noticed..
|
|