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


Groups > comp.unix.shell > #4378

Re: Why 'break' even has effects outside of its function?

From Kaz Kylheku <kaz@kylheku.com>
Newsgroups comp.unix.shell
Subject Re: Why 'break' even has effects outside of its function?
Date 2012-03-07 09:39 +0000
Organization Aioe.org NNTP Server
Message-ID <20120307010429.677@kylheku.com> (permalink)
References <jj1t5r$nsj$1@wangcong.dont-email.me> <jj309m$7d9$1@news.m-online.net> <jj3du8$jqm$1@speranza.aioe.org> <20120306215813.85@kylheku.com> <jj77u1$jn3$1@speranza.aioe.org>

Show all headers | View raw


On 2012-03-07, Alan Curry <pacman@kosh.dhis.org> wrote:
> In article <20120306215813.85@kylheku.com>,
> Kaz Kylheku  <kaz@kylheku.com> wrote:
>>On 2012-03-05, Alan Curry <pacman@kosh.dhis.org> wrote:
>>> Right, but the second parsing is done on the eval'ed command line later, and
>>> the parsing of the loop is not in progress at the same time, so it's weird to
>>> think of the loop as "lexically enclosing" the second parse. It's more
>>> natural (for me at least) that eval should create a new top-level lexical
>>> environment.
>>
> [...]
>>
>>Anyway, the standard shell language does not have lexical /anything/.
>>Just top level functions and variables.
>
> The shell itself contains a parser for the language. An obvious
> implementation would create a new one of those, with no way of knowing
> whether it's inside a loop in the outer execution environment, and thus no
> way to influence an outer loop's execution.
>
>>
>>For instance you can write a function which accepts a variable
>>name (for a variable in the calling environment) and can change its value.
>
> Having access to variables is nowhere near as deep a relationship as having
> access to the execution control stack that keps track loops currently in
> progress!

It is exactly the same thing. The control stack contains variables that
keep track of this.

>
>>In Bash, your eval'ed code can not only refer to the variable whose name
>>was passed in, but also to the local variables in the function.
>
> Global variables are accessible everywhere, including functions and evals.
> That doesn't seem like a big deal to me.
>
>>
>>You can write a function which controls the evaluation of syntax
>>that is passed in:
>
> This should be good...
>
>>
>>dotimes ()
>>{
>>  local __count_var=$1
>>  local __max_count=$2
>>  local __count=0
>>
>>  shift; shift;
>>
>>  while [ $__count -lt $__max_count ] ; do
>>     eval $__count_var=\$__count;
>
> I think that would be just as good without the backslash.

Yes, but only because we control __count and we know that __count contains a
number. A double evaluation of a number just yields that number.

In the general case, we want that dollar sign to survive into the eval, so the
eval will properly evaluate $__count, expanding just once.

> And indirect
> assignments are surely one of the most common uses of eval, so not
> surprising.
>
>>     eval "$@"
>
> Whether this is a spooky eval or not depends on what the caller put in it...

Not really. Unless the caller knows about __count_var and __count, 
the eval will behave in an expected way.

>>     __count=$(( __count + 1 ))
>>  done
>>}
>>
>>dotimes x 10 'printf "x = %d\n" $x'
>
> And this caller doesn't put anything interesting there. This works perfectly
> in pdksh, which doesn't support "eval break". 

Thus, it is inconsistent.

> If you try
>
> dotimes x 10 'printf "x = %d\n" $x;break'
>
> then most shells just print "x = 0" and quit,

But that is a feature! break bails out of dotimes properly. dotimes is a wrapper
around a while loop.

>>Bash does the "right thing" by conforming to the expectations of shell coders,
>>The alternative is to die with an error, which is nonproductive.
>
> pdksh does the "right thing" by telling the coder he's nuts.

Which is out of place in a language that allows nutty eval hacks.

Bash is consistent.

>>
>>That naive behavior is not so naive: it lets you do things that are not
>>possible otherwise.
>>
>>Now here is my point. Think about this.  Suppose the above "eval $br" were to
>>die with error like "bash: break: only meaningful in a `for', `while', or
>
> ...like pdksh's error message but more verbose....
>
>>`until' loop".  Given that we can write the dotimes function above, with
>>the crazy eval hacks that work, and that we have to hide our local variables
>>with underscores, etc, don't you think that this diagnostic would be
>>/laughably/ inconsistent?
>
> Me and pdksh don't think so, since we see looping control structures as
> super-low-level stuff that should resolve at parse time, and shell variables
> as a simple global mapping of strings to other strings.

That is laughably inconsistent. Part of the language has delusions of grandeur
about becoming a compiled language one day, and part of the language is
a dynamically scoped hack. 

Simple global mapping? Are there no locals then?


>
>>
>>> Some of us just think of "break" as being bound to the enclosing "while" in
>>> exactly the same syntactic manner as the "done" that ends it.
>>
>>done is just punctuation, like a closing parenthesis.  break has semantics of
>>its own.
>>
>>Moreover, you do not necessarily know, statically, where it goes. Remember, it
>>takes an argument: break $run_time_value .
>
> Oh hell, that seals it. All the previous examples are only slightly spooky.
> That's like a computed goto.

Precisely: with N nestings, there are N possible target points, selected by number.
Nothing "like" about it.

> No... it's more than that. Combined with the
> ability to break out of a function, you can't even know how many functions
> you'll be prematurely remotely terminating. It's pure evil... it's LONGJMP!

It would be even more like longjmp if it used named blocks instead.

 break main_event_loop_way_up_high

> The Bourne shell has been hiding a longjmp equivalent all this time. Must
> wash hands... can't get clean...

But bash has the internal unwind-protect to undo the local variables, whereas
longjmp doesn't clean up (unless you wrap some functionality around it and use
only the disciplined interface).

  # global x
  x=42

  func()
  {
     local x=0
     break;
  }

  while true; do
    func
  done

  echo $x

Output:

  42

longjmp, but with proper unwinding of the dynamic scope which restores the
global value of x.

Man is this break hack ever well-supported, wouldn't you say. :)

I'd be curious what happens if you step through this in the bash debugger, bashdb.
Will it preserve the semantics? Ha.

Back to comp.unix.shell | Previous | NextPrevious in thread | Next in thread | Find similar | Unroll thread


Thread

Why 'break' even has effects outside of its function? Cong Wang <xiyou.wangcong@gmail.com> - 2012-03-05 08:23 +0000
  Re: Why 'break' even has effects outside of its function? Lew Pitcher <lpitcher@teksavvy.com> - 2012-03-05 01:03 -0800
    Re: Why 'break' even has effects outside of its function? Cong Wang <xiyou.wangcong@gmail.com> - 2012-03-05 09:42 +0000
      Re: Why 'break' even has effects outside of its function? Kaz Kylheku <kaz@kylheku.com> - 2012-03-05 13:59 +0000
      Re: Why 'break' even has effects outside of its function? Janis Papanagnou <janis_papanagnou@hotmail.com> - 2012-03-05 15:40 +0100
        Re: Why 'break' even has effects outside of its function? Kaz Kylheku <kaz@kylheku.com> - 2012-03-05 15:18 +0000
          Re: Why 'break' even has effects outside of its function? "Ed Morton" <mortonspam@gmail.com> - 2012-03-05 16:03 +0000
            Re: Why 'break' even has effects outside of its function? Kaz Kylheku <kaz@kylheku.com> - 2012-03-05 16:37 +0000
              Re: Why 'break' even has effects outside of its function? "Ed Morton" <mortonspam@gmail.com> - 2012-03-05 17:49 +0000
                Re: Why 'break' even has effects outside of its function? gazelle@shell.xmission.com (Kenny McCormack) - 2012-03-05 18:02 +0000
                Re: Why 'break' even has effects outside of its function? Ed Morton <mortonspam@gmail.com> - 2012-03-05 17:57 -0600
          Re: Why 'break' even has effects outside of its function? Janis Papanagnou <janis_papanagnou@hotmail.com> - 2012-03-05 19:22 +0100
            Re: Why 'break' even has effects outside of its function? pacman@kosh.dhis.org (Alan Curry) - 2012-03-05 22:15 +0000
              Re: Why 'break' even has effects outside of its function? Janis Papanagnou <janis_papanagnou@hotmail.com> - 2012-03-06 12:04 +0100
                Re: Why 'break' even has effects outside of its function? pacman@kosh.dhis.org (Alan Curry) - 2012-03-06 23:10 +0000
              Re: Why 'break' even has effects outside of its function? Kaz Kylheku <kaz@kylheku.com> - 2012-03-07 05:58 +0000
              Re: Why 'break' even has effects outside of its function? Kaz Kylheku <kaz@kylheku.com> - 2012-03-07 05:58 +0000
              Re: Why 'break' even has effects outside of its function? Kaz Kylheku <kaz@kylheku.com> - 2012-03-07 07:25 +0000
                Re: Why 'break' even has effects outside of its function? pacman@kosh.dhis.org (Alan Curry) - 2012-03-07 08:57 +0000
                Re: Why 'break' even has effects outside of its function? Kaz Kylheku <kaz@kylheku.com> - 2012-03-07 09:39 +0000
                Re: Why 'break' even has effects outside of its function? pacman@kosh.dhis.org (Alan Curry) - 2012-03-08 01:28 +0000
                Re: Why 'break' even has effects outside of its function? Sven Mascheck <mascheck@email.invalid> - 2012-03-13 22:50 +0000
                Re: Why 'break' even has effects outside of its function? Kaz Kylheku <kaz@kylheku.com> - 2012-03-13 23:00 +0000
                Re: Why 'break' even has effects outside of its function? Kaz Kylheku <kaz@kylheku.com> - 2012-03-14 05:59 +0000
            Re: Why 'break' even has effects outside of its function? Kaz Kylheku <kaz@kylheku.com> - 2012-03-07 05:48 +0000
          Re: Why 'break' even has effects outside of its function? Barry Margolin <barmar@alum.mit.edu> - 2012-03-05 13:29 -0500

csiph-web