Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #103321 > unrolled thread

need {..} block, and switch case, need, and needs keywords

Started by"Rick C. Hodgin" <rick.c.hodgin@gmail.com>
First post2017-02-06 07:57 -0800
Last post2017-02-08 05:43 -0800
Articles 10 — 3 participants

Back to article view | Back to comp.lang.c


Contents

  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

#103321 — need {..} block, and switch case, need, and needs keywords

From"Rick C. Hodgin" <rick.c.hodgin@gmail.com>
Date2017-02-06 07:57 -0800
Subjectneed {..} 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]


#103324

FromBartC <bc@freeuk.com>
Date2017-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]


#103328

From"Rick C. Hodgin" <rick.c.hodgin@gmail.com>
Date2017-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]


#103345

FromDavid Brown <david.brown@hesbynett.no>
Date2017-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]


#103367

From"Rick C. Hodgin" <rick.c.hodgin@gmail.com>
Date2017-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]


#103431

FromDavid Brown <david.brown@hesbynett.no>
Date2017-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]


#103448

From"Rick C. Hodgin" <rick.c.hodgin@gmail.com>
Date2017-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]


#103460

FromDavid Brown <david.brown@hesbynett.no>
Date2017-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]


#103462

From"Rick C. Hodgin" <rick.c.hodgin@gmail.com>
Date2017-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]


#103464

From"Rick C. Hodgin" <rick.c.hodgin@gmail.com>
Date2017-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