Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #103321 > unrolled thread
| Started by | "Rick C. Hodgin" <rick.c.hodgin@gmail.com> |
|---|---|
| First post | 2017-02-06 07:57 -0800 |
| Last post | 2017-02-08 05:43 -0800 |
| Articles | 10 — 3 participants |
Back to article view | Back to comp.lang.c
need {..} block, and switch case, need, and needs keywords "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2017-02-06 07:57 -0800
Re: need {..} block, and switch case, need, and needs keywords BartC <bc@freeuk.com> - 2017-02-06 16:23 +0000
Re: need {..} block, and switch case, need, and needs keywords "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2017-02-06 08:36 -0800
Re: need {..} block, and switch case, need, and needs keywords David Brown <david.brown@hesbynett.no> - 2017-02-07 09:39 +0100
Re: need {..} block, and switch case, need, and needs keywords "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2017-02-07 07:32 -0800
Re: need {..} block, and switch case, need, and needs keywords David Brown <david.brown@hesbynett.no> - 2017-02-08 09:43 +0100
Re: need {..} block, and switch case, need, and needs keywords "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2017-02-08 03:26 -0800
Re: need {..} block, and switch case, need, and needs keywords David Brown <david.brown@hesbynett.no> - 2017-02-08 14:30 +0100
Re: need {..} block, and switch case, need, and needs keywords "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2017-02-08 05:38 -0800
Re: need {..} block, and switch case, need, and needs keywords "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2017-02-08 05:43 -0800
| From | "Rick C. Hodgin" <rick.c.hodgin@gmail.com> |
|---|---|
| Date | 2017-02-06 07:57 -0800 |
| Subject | need {..} block, and switch case, need, and needs keywords |
| Message-ID | <cccf37f2-ec4b-4780-a406-ac52f46e8c79@googlegroups.com> |
I had an idea for injecting code into a system which is tied to a needs
keyword used later in flow control. Consider the needs of this a switch
{..} block, having some code which would only be executed if flow reached
a certain point.
switch (x)
{
case 0:
break;
case 1:
break;
case 2:
break;
default:
value = get_something(); /* Possibly expensive call, therefore
only issued if flow reaches here */
// Continue testing
switch (x)
{
case 3:
// "value" is used here
break;
case 4:
value2 = get_something_else();
// "value" and "value2" are valid and in scope here
break;
default:
// Not found
break;
}
}
I had the idea of creating the need keyword for definition, and the
needs keyword for use:
switch (x)
{
need val:
// Documentation about why this would be needed
value = get_something();
break;
need val2:
// Documentation about why this would be needed
value2 = get_something_else();
break;
case 0:
break;
case 1:
break;
case 2:
break;
case 3 needs val:
// "value" is used here
break;
case 4 needs val, val2:
// "value" and "value2" are used here
break;
default:
// Not found
break;
}
-----
In addition, the more general form could be used in code with
independently named blocks which can be executed only when needed
in the runtime flow of the code:
need val {
// Documentation about why this would be needed
int value = get_something();
}
need val2 {
// Documentation about why this would be needed
int value2 = get_something_else();
}
if (x) needs val
{
// value is valid and in scope here
} else if (y) {
// Neither value or value2 are valid or in scope here
} else if (z) needs val, val2 {
// value and value2 are valid and in scope here
} else {
// Neither value or value2 are valid or in scope here
}
In these cases, only if the block is entered at x or z is the
associated need {..} code block(s) executed, and valid in scope.
Thank you,
Rick C. Hodgin
[toc] | [next] | [standalone]
| From | BartC <bc@freeuk.com> |
|---|---|
| Date | 2017-02-06 16:23 +0000 |
| Message-ID | <o7a7r6$f4a$1@dont-email.me> |
| In reply to | #103321 |
On 06/02/2017 15:57, Rick C. Hodgin wrote:
> I had an idea for injecting code into a system which is tied to a needs
> keyword used later in flow control. Consider the needs of this a switch
> {..} block, having some code which would only be executed if flow reached
> a certain point.
>
> switch (x)
> {
> case 0:
> break;
> case 1:
> break;
> case 2:
> break;
>
> default:
> value = get_something(); /* Possibly expensive call, therefore
> only issued if flow reaches here */
> // Continue testing
> switch (x)
> {
> case 3:
> // "value" is used here
> break;
> case 4:
> value2 = get_something_else();
> // "value" and "value2" are valid and in scope here
> break;
> default:
> // Not found
> break;
> }
>
> }
>
> I had the idea of creating the need keyword for definition, and the
> needs keyword for use:
>
> switch (x)
> {
> need val:
> // Documentation about why this would be needed
> value = get_something();
> break;
> need val2:
> // Documentation about why this would be needed
> value2 = get_something_else();
> break;
>
> case 0:
> break;
> case 1:
> break;
> case 2:
> break;
>
> case 3 needs val:
> // "value" is used here
> break;
> case 4 needs val, val2:
> // "value" and "value2" are used here
> break;
>
> default:
> // Not found
> break;
> }
>
> -----
> In addition, the more general form could be used in code with
> independently named blocks which can be executed only when needed
> in the runtime flow of the code:
>
> need val {
> // Documentation about why this would be needed
> int value = get_something();
> }
>
> need val2 {
> // Documentation about why this would be needed
> int value2 = get_something_else();
> }
This is similar to the flow blocks you mentioned a couple of years back.
I actually implemented something along those lines which can do the
above. Example (not in C):
proc start=
int x
int value=0, value2=0
x:=4
switch x
when 0 then
when 1 then
when 2 then
when 3 then
@getval
println value
when 4 then
@getval
@getval2
println value,value2
else
end switch
println "ABC"
blockdef getval=
value:=100
end
blockdef getval2=
value:=200
end
println "DEF"
end
When x is 4, the output is:
100 200
ABC
DEF
(The ABC/DEF shows it 'steps around' those block definitions.)
The C output is (requiring gcc's label pointers, otherwise it's trickier
and less efficient):
void start (void) {
int32 x;
int32 value=0;
int32 value2=0;
int32 * av_1;
int32 * av_2;
x = 4;
switch (x) {
case 0:
break;
case 1:
break;
case 2:
break;
case 3:
av_1=&&L2;
goto L1;
L2:;
printf("%d\n",value);
break;
case 4:
av_1=&&L3;
goto L1;
L3:;
av_2=&&L5;
goto L4;
L5:;
printf("%d %d\n",value,value2);
break;
default:;
}
printf("%s\n","ABC");
goto L6;
L1:;
value = 100;
goto *av_1;
L6:;
goto L7;
L4:;
value2 = 200;
goto *av_2;
L7:;
printf("%s\n","DEF");
}
The feature is still there but I never use and in the next version it
would have been dropped. There just seems something 'off' about it.
--
Bartc
[toc] | [prev] | [next] | [standalone]
| From | "Rick C. Hodgin" <rick.c.hodgin@gmail.com> |
|---|---|
| Date | 2017-02-06 08:36 -0800 |
| Message-ID | <419584ec-2806-465f-82b9-7e609dd69b13@googlegroups.com> |
| In reply to | #103324 |
On Monday, February 6, 2017 at 11:23:51 AM UTC-5, Bart wrote: > This is similar to the flow blocks you mentioned a couple of years back. Correct. The purpose of the flow block is to better document code, and to move potentially well-indented to a place where it's less indented. It also allows for local functions to be defined which are specific to the one block. In this case, it's done similarly so that it can better document code, but in this case also without having to dip into the more syntax- intensive flow blocks. Thank you, Rick C. Hodgin
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2017-02-07 09:39 +0100 |
| Message-ID | <o7c11a$ti7$1@dont-email.me> |
| In reply to | #103321 |
On 06/02/17 16:57, Rick C. Hodgin wrote:
> I had an idea for injecting code into a system which is tied to a needs
> keyword used later in flow control. Consider the needs of this a switch
> {..} block, having some code which would only be executed if flow reached
> a certain point.
>
> switch (x)
> {
> case 0:
> break;
> case 1:
> break;
> case 2:
> break;
>
> default:
> value = get_something(); /* Possibly expensive call, therefore
> only issued if flow reaches here */
> // Continue testing
> switch (x)
> {
> case 3:
> // "value" is used here
> break;
> case 4:
> value2 = get_something_else();
> // "value" and "value2" are valid and in scope here
> break;
> default:
> // Not found
> break;
> }
>
> }
>
As is often the case with these ideas, I find it hard to understand why
you need to find new keywords and new syntax when there are already
reasonable ways to implement the effect - such as the code you posted above.
You have to think hard about how often a feature really would be useful.
If it is rare, then it would be better for users to have to write
slightly odd code (such as above) than for them to have to learn new
syntaxes and new keywords for something they don't use often.
You also need to think about how changes like this would affect your
language. A "switch" in C looks at the switch value, then jumps
directly to the corresponding case label - it does /not/ pass through
statements in between. Be wary of how something like this "need" idea
might change existing concepts.
And rather than jumping into specialised cases, perhaps there is scope
for something that gives simpler and clearer code for the user, letting
the /compiler/ do the work in generate optimal code. Consider a format:
value = [[discardable]] get_something();
This tells the compiler that /if/ you use "value", then it needs to call
"get_something()". But the call is "discardable" - if the result is not
used, the call can be discarded. Then in each switch case, if "value"
is used the compiler must ensure that "get_something()" is called - if
it is not used, then it is (or may not be) not called. This means that
the compiler does the work of figuring out the best arrangement, not the
user - the "needs" stuff is automatic.
(I am not saying that your "need" is necessarily a bad idea - I am
merely recommending you think about it more.)
[toc] | [prev] | [next] | [standalone]
| From | "Rick C. Hodgin" <rick.c.hodgin@gmail.com> |
|---|---|
| Date | 2017-02-07 07:32 -0800 |
| Message-ID | <812f2dea-9a1e-4286-9d57-2be0213f6a53@googlegroups.com> |
| In reply to | #103345 |
On Tuesday, February 7, 2017 at 3:39:57 AM UTC-5, David Brown wrote: > value = [[discardable]] get_something(); I think this would move the definition too far away from use, and require a greater effort to hunt down and discover its use when doing later maintenance or debugging. Thank you, Rick C. Hodgin
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2017-02-08 09:43 +0100 |
| Message-ID | <o7elkr$f8u$1@dont-email.me> |
| In reply to | #103367 |
On 07/02/17 16:32, Rick C. Hodgin wrote: > On Tuesday, February 7, 2017 at 3:39:57 AM UTC-5, David Brown wrote: >> value = [[discardable]] get_something(); > > I think this would move the definition too far away from use, and > require a greater effort to hunt down and discover its use when doing > later maintenance or debugging. > No, it would not. It would make the "optional" or "discardable" nature of the call to get_something at precisely the location you want - where get_something is called. And it would make the use of the variable "value" obvious too - you use it if you need it, you don't use it if you don't need it. Why should the programmer also have to write "needs value" as well? And if the programmer's use of "value" is so far away from the call that sets it, then their function is too long and complicated - and that's not a style to encourage.
[toc] | [prev] | [next] | [standalone]
| From | "Rick C. Hodgin" <rick.c.hodgin@gmail.com> |
|---|---|
| Date | 2017-02-08 03:26 -0800 |
| Message-ID | <bafcfb55-653d-4a9b-a349-17d410d48fca@googlegroups.com> |
| In reply to | #103431 |
David Brown wrote:
> It would make the "optional" or "discardable" nature of the call
> to get_something at precisely the location you want -where
> get_something is called.
If that's your idea, then I'm back to programming every logic
step manually, as in my original exame. The whole purpose of the
needs {..} block is to simplify that while better documenting the code.
> And it would make the use of the variable "value" obvious
> too - you use it if you need it, you don't use it if you don't need it.
> Why should the programmer also have to write "needs value" as well?
It documents what it needs in these cases where the value(s)
are only needed in a subset of all formal cases, and it removes the
mechanics of underlying work, substituting it with a descriptive name,
making it easier to understand to new people examining the code.
-----
You have polar opposite thinking to mine on almost all areas.
I have responded as much as I have, but I haven't seen anything
positive come out of our exchanges, just rigid differences of views.
I may stop responding to you because of it, as each post you offer
feels like an certain type of attack.
Thank you,
Rick C. Hodgin
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2017-02-08 14:30 +0100 |
| Message-ID | <o7f6es$6f4$1@dont-email.me> |
| In reply to | #103448 |
On 08/02/17 12:26, Rick C. Hodgin wrote:
> David Brown wrote:
>> It would make the "optional" or "discardable" nature of the call
>> to get_something at precisely the location you want -where
>> get_something is called.
>
> If that's your idea, then I'm back to programming every logic
> step manually, as in my original exame. The whole purpose of the
> needs {..} block is to simplify that while better documenting the code.
>
I think you must have misunderstood what I meant. My version of your
switch would be:
value = [[discardable]] get_something();
switch (x) {
case 0: break;
case 1: break;
case 2: break;
case 3:
// "value" is used here
break;
case 4:
value2 = get_something_else();
// "value" and "value2" are valid and in scope
break;
default:
// Not found
break;
}
>> And it would make the use of the variable "value" obvious
>> too - you use it if you need it, you don't use it if you don't need it.
>> Why should the programmer also have to write "needs value" as well?
>
> It documents what it needs in these cases where the value(s)
> are only needed in a subset of all formal cases, and it removes the
> mechanics of underlying work, substituting it with a descriptive name,
> making it easier to understand to new people examining the code.
>
> -----
> You have polar opposite thinking to mine on almost all areas.
> I have responded as much as I have, but I haven't seen anything
> positive come out of our exchanges, just rigid differences of views.
> I may stop responding to you because of it, as each post you offer
> feels like an certain type of attack.
>
If my posts feel like an attack, it is because you are not open to
discussion - you are not ready to accept that there can be other ideas
or ways to improve your ideas. Stop acting as though the /first/
thought that pops into your head has to be the /only/ thought - let your
ideas mature and warp through your own thought and discussions with
others. Let yourself be inspired by something other than your own ideas.
I will often criticise what you write - but it is /constructive/
criticism. Sometimes I feel an idea you have is absolutely daft and
counter-productive to good programming - and I will say so, rather than
lying to you. Your aim is to build a useful and productive programming
language, not a child's drawing to hang on the fridge. So if I feel you
are going in completely the wrong direction with something, that's what
I will say - because in my opinion, your time and energy would be better
spent in a different direction. It is, of course, entirely up to /you/
to decide if you agree with me - but I am advising you to the best of my
knowledge, not /attacking/ you or your work.
In this particular case, I think your idea is bad - I think it
introduces complications in syntax, extra keywords, and makes it hard
for a programmer to follow what is going on. However, it gave rise to
an alternative idea that I think is better - it has minimal syntax,
minimal extra effort for the programmer, but would be more useful in a
wider range of circumstances. If you don't like this new idea, then
that's fine - don't use it. But don't take it as an attack.
[toc] | [prev] | [next] | [standalone]
| From | "Rick C. Hodgin" <rick.c.hodgin@gmail.com> |
|---|---|
| Date | 2017-02-08 05:38 -0800 |
| Message-ID | <3191cfac-1f48-4ae2-9dc4-d9fb6bf57863@googlegroups.com> |
| In reply to | #103460 |
On Wednesday, February 8, 2017 at 8:30:54 AM UTC-5, David Brown wrote:
> On 08/02/17 12:26, Rick C. Hodgin wrote:
> > David Brown wrote:
> >> It would make the "optional" or "discardable" nature of the call
> >> to get_something at precisely the location you want -where
> >> get_something is called.
> >
> > If that's your idea, then I'm back to programming every logic
> > step manually, as in my original exame. The whole purpose of the
> > needs {..} block is to simplify that while better documenting the code.
>
> I think you must have misunderstood what I meant. My version of your
> switch would be:
>
> value = [[discardable]] get_something();
> switch (x) {
> case 0: break;
> case 1: break;
> case 2: break;
> case 3:
> // "value" is used here
> break;
> case 4:
> value2 = get_something_else();
> // "value" and "value2" are valid and in scope
> break;
> default:
> // Not found
> break;
> }
Yes. It is similar in concept to what I indicate with the need {..}
block, and needs keyword, but it doesn't document the operation at
the place of use (in each case statement), and it doesn't encapsulate
the components specific to those needs, and it is limited in its
operation because you cannot do multiple things with your [[discardable]]
notation, but only assign lazy-assigned values into variables.
With a need {..} block you can perform multiple logic steps only
when required. The compiler will figure out the best way to insert
them for you, you just need to specify "needs xyz" in order to use
it, where you need it, which documents its use.
> >> And it would make the use of the variable "value" obvious
> >> too - you use it if you need it, you don't use it if you don't need it.
> >> Why should the programmer also have to write "needs value" as well?
> >
> > It documents what it needs in these cases where the value(s)
> > are only needed in a subset of all formal cases, and it removes the
> > mechanics of underlying work, substituting it with a descriptive name,
> > making it easier to understand to new people examining the code.
> >
> > -----
> > You have polar opposite thinking to mine on almost all areas.
> > I have responded as much as I have, but I haven't seen anything
> > positive come out of our exchanges, just rigid differences of views.
> > I may stop responding to you because of it, as each post you offer
> > feels like an certain type of attack.
>
> If my posts feel like an attack...[snip]
This will be my last response to you, David.
I do appreciate your desires to try and help and improve me in my
life. It is a very admirable thing to desire to do, and it has not
gone unnoticed by me. I personally thank you for your assistance
these many years, and I wish you the best in your endeavors.
Thank you,
Rick C. Hodgin
[toc] | [prev] | [next] | [standalone]
| From | "Rick C. Hodgin" <rick.c.hodgin@gmail.com> |
|---|---|
| Date | 2017-02-08 05:43 -0800 |
| Message-ID | <47dd0579-3e71-4b73-b21c-501843469c5d@googlegroups.com> |
| In reply to | #103462 |
On Wednesday, February 8, 2017 at 8:38:13 AM UTC-5, Rick C. Hodgin wrote:
> With a need {..} block you can perform multiple logic steps only
> when required. The compiler will figure out the best way to insert
> them for you, you just need to specify "needs xyz" in order to use
> it, where you need it, which documents its use.
One further note, need {..} blocks do not need to be local in scope.
They can be global, used everywhere, just like the phase {..} blocks
I proposed for for {..} loops, or contained within a parent (like in
a class or struct).
Thank you,
Rick C. Hodgin
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.c
csiph-web