Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: Bug with unset variables



On Fri, Nov 13, 2020 at 11:41 PM Roman Perepelitsa
<roman.perepelitsa@xxxxxxxxx> wrote:
>
> On Sat, Nov 14, 2020 at 1:52 AM Felipe Contreras
> <felipe.contreras@xxxxxxxxx> wrote:
> >
> > In JavaScript if you don't declare foo, accessing it gives you the
> > value of "undefined", and if you declare it and "unset" it, it also
> > gives you "undefined".
>
> Here's what I'm getting in Chrome console:
>
>   console.log(foo)
>
>     Uncaught ReferenceError: foo is not defined
>
>   foo = undefined
>   console.log(foo)
>
>     undefined
>
> Is this behavior non-standard?

We are talking about local variables. Did you declare 'foo' as a local variable?

Moreover, JavaScript has the notion of hoisted variables:

  console.log(foo); # undefined
  var foo;

> > You just don't want to accept they are functionally the same because
> > you don't want them to be the same.
>
> Let's keep the discussion limited to the subject matter of programming
> languages.

The interpretation of language is directly related to programming languages.

You want to ignore an interpretation because it's inconvenient for you.

It is a fact the two are functionally the same.

> > Lisp doesn't allow defining variables without a value.

> A variable declared without a value gets the value of nil. You can
> pass nil around like any other value.

If "(let ((var)) ...)" is the same as "(let ((var nil)) ...)", then
it's *exactly* the same as "var = None" in Python.

> > you have avoided some of my strongest arguments, for example this:
> >
> >   func () {
> >     [[ -n "$1" ]] && var=$1
> >     dosomething ${var-other}
> >   }
> >
> >   func () {
> >     typeset var
> >     [[ -n "$1" ]] && var=$1
> >     dosomething ${var-other}
> >   }
> >
> > You have never explained how it makes sense that adding that extra
> > line changes the behavior.
>
> I thought you were arguing that the behavior of `typeset var` in
> ksh/bash makes sense while in zsh it doesn't. However, in the example
> you've given above adding `typeset var` to func changes the function's
> behavior in all shells. What am I missing?

It doesn't change the behavior of the function func(), it only changes
the scope of the variable "var" (like in all languages).

You know what the behavior of the original func() was. It seems you
are being obtuse on purpose.

> > > Moreover, [in Lua] variables to which nil has been assigned are
> > > indistinguishable from variables that have never been declared.
> > > "Variable foo is nil" has the same meaning as "variable foo does not
> > > exist". Like in shells and unlike JavaScript.
> >
> > Exactly the same thing as in JavaScript, just s/nil/undefined/.
>
> If you try to print a variable that hasn't been defined, you'll get an
> error in JavaScript and "nil" in Lua.

Declared is not the same as defined.

  func () {
    var foo;
  }

Foo is undefined, but declared with a local scope.

> > Either way, "local x" in Lua does exactly the same thing as it does in Bash.
>
> That was my point. Originally I said I didn't know of any language
> that does what ksh/bash does but then I realized that Lua could fit
> the bill, so I mentioned it. To be more specific, I was looking for a
> language that 1) allows you to declare variables without specifying
> their values; 2) allows you to unset/unbind/undeclare variables; 3)
> the effect of declaring a variable and immediately unsetting it is
> equivalent to declaring a variable without specifying the initial
> value.

1) But you ignore the languages that can use nil, which is
functionally the same as no-value.

2) But you ignore the languages that can unset the value of a variable
(using nil), which is functionally the same as no-value.

3) Which makunbound doesn't do in elisp (and var=nil does do on
virtually all languages).

> FWIW, one of my gripes with Lua is that accessing an undeclared
> variable gives you nil. If it was an error instead (which I would
> prefer), Lua wouldn't satisfy the 3rd requirement I've listed above,
> so it wouldn't be like ksh/bash for the purpose of this discussion. It
> would be like zsh and elisp.

It does satisfy 3), you just do want to accept it.

  local foo
  print(foo)

Is *exactly* the same as:

  local foo
  foo = nil -- unset
  print(foo)

All languages we explored have the same notion (inside a function):

JavaScript:

  var foo;
  console.log(foo); # undefined
  foo = 'set';
  foo = undefined' # unset()
  console.log(foo); # undefined

Python:

  foo = None
  print(foo) # None
  foo = "set"
  foo = None # unset()
  print(foo) # None

Ruby:

  foo = nil
  p foo # nil
  foo = "set"
  foo = nil # unset()
  p foo # nil

Lua:

  local foo
  print(foo) # nil
  foo = 'set'
  foo = nil # unset()
  print(foo) # nil

Emacs Lisp:

  (defun foo ()
    (let ((var))
      (print var) ; nil
      (set 'var "set")
      (set 'var nil) ; unset
      (print var) ; nil
    )
  )

Shell:

  local foo
  echo ${foo-nil} # nil
  foo="set"
  unset foo
  echo ${foo-nil} # nil

These are all functionally *exactly* the same. And that's an undeniable fact.

> > The most straightforward way is not necessarily the best way.
> >
> > Very often the best way takes effort.
>
> This is obviously true.
>
> I'll summarize my position. I believe it is in agreement with Peter
> and Bart but I wouldn't presume speaking for them.
>
> - The way typeset works in zsh makes sense. There is no inconsistency,
> there is precedence in other languages, and it was a natural evolution
> from global-only parameters.

That is an opinion. I disagree.

> - If we could change history, it would be better if typeset in zsh
> worked the same way as in ksh/bash because that behavior also makes
> sense and compatibility is valuable.

Indeed.

> - It's infeasible to change the behavior of typeset in zsh in native
> mode because it'll break too much user code.

Nothing is impossible. It's just harder when you don't even think of trying it.

> - It's feasible and desirable to make typeset compatible with ksh/bash
> when KSH_TYPESET is set.

KSH_TYPESET does something else that not even ksh does. But another
option might make sense.

Cheers.

-- 
Felipe Contreras




Messages sorted by: Reverse Date, Date, Thread, Author