8

According to Advanced Bash-Scripting Guide,

  1. bash variables are untyped:

    Unlike many other programming languages, Bash does not segregate its variables by "type." Essentially, Bash variables are character strings, but, depending on context, Bash permits arithmetic operations and comparisons on variables. The determining factor is whether the value of a variable contains only digits.

    The link also gives examples.

    Does "untyped" mean the same as the concept of "dynamically typing" in programming languages? If not, what are the relations and differences between the two?

  2. To lighten the burden of keeping track of variable types in a script, Bash does permit declaring variables.

    For example, declare a variable to be integer type, by declare -i myvariable.

    Is this called "typed" variables? Does "typed" mean the same as the concept of "statically typing"?

Bhargav Rao
  • 50,140
  • 28
  • 121
  • 140
Tim
  • 1
  • 141
  • 372
  • 590
  • 1
    This is actually a really interesting question, please don't close I've learned ton from this even after reading the other answers. – Harry Apr 24 '16 at 06:51
  • 1
    It's a bit hazy whether `declare -i` actually provides any notion of type, if only because there are so few places where a distinction could be drawn. Assignment to a variable with its integer attribute set is affected, but nowhere else is the *use* of such a variable distinguishable from a variable without the attribute set. – chepner Apr 24 '16 at 14:05

2 Answers2

3

Most of this has been well answered here...

Does "untyped" also mean "dynamically typed" in the academic CS world?

by at least two people that are very familiar with the matter. To most of us that have not studied type systems etc to that level 'untyped' means dynamic typing but it's a misnomer in academic circles, see post above. untyped actually means there are no types ie think assembly, Bash is typed, it figures out it's types at runtime. Lets take the following sentence from the Advanced Bash Scripting Guide, emphasis mine...

http://tldp.org/LDP/abs/html/untyped.html

Unlike many other programming languages, Bash does not segregate its variables by "type." Essentially, Bash variables are character strings, but, depending on context, Bash permits arithmetic operations and comparisons on variables. The determining factor is whether the value of a variable contains only digits.

Bash figures out that something is a number at runtime ie it's dynamically typed. In assembler on a 64bit machine I can store any 8 bytes in a register and decrement it, it doesn't check to see if the things were chars etc, there is no context about the thing it's about to decrement it just decrements the 64 bits, it doesn't check or work out anything about the type of the thing it's decrementing.

Perl is not an untyped language but the following code might make it seem like it treats everything as integers ie

#!/usr/bin/perl
use strict;
use warnings;
my $foo = "1";
my $bar = $foo + 1;
print("$bar\n");

$foo was assigned a string but was incremented? Does this means Perl is untyped because based on context it does what you want it to do? I don't think so.

This differs from Python, Python will actually give you the following error if you try the same thing...

Traceback (most recent call last):
  File "py.py", line 2, in <module>
  bar = foo + 1

If Python is dynamically typed and Perl is dynamically typed why do we see different behavior. Is it because their type systems differ or their type conversion semantics differ. In assembly do we have type conversion instructions that change a string to an integer or vice versa?

Bash has different type conversion rules

#!/bin/bash
set -e
MYVAR=WTF
let "MYVAR+=1"
echo "MYVAR == $MYVAR";

This will assign 1 to MYVAR instead of incrementing it ie if you increment a string bash sets the string to integer zero then does the increment. It's performing type conversion which means it's typed.

For anyone still believing that Bash is untyped try this....

#!/bin/bash
declare -i var1=1
var1=2367.1

You should get something like this...

foo.sh: line 3: 2367.1: syntax error: invalid arithmetic operator (error token is ".1")

But the following shows no such error

#!/bin/bash
var1=2367.1

The output of the following

#!/bin/bash
var1=2367.1
echo "$var1"
let "var1+=1"
echo "$var1"

is the same warning without declaring a type...

2367.1
foo.sh: line 4: let: 2367.1: syntax error: invalid arithmetic operator (error token is ".1")
2367.1

A much better example is this

#!/bin/bash
arg1=1234
arg2=abc

if [ $arg1 -eq $arg2 ]; then
  echo "wtf";
fi

Why do I get this...

foo.sh: line 5: [: abc: integer expression expected

Bash is asking me for an integer expression.

Community
  • 1
  • 1
Harry
  • 11,298
  • 1
  • 29
  • 43
  • 4
    I disagree with this answer. Bash is *not* typed. There are only strings, and you can perform both string and arithmetic operations on them. By contrast, Python is dynamically typed. It distinguishes between `1` the integer and `"1"` the string and you cannot perform arithmetic on `"1"`. – John Kugelman Apr 24 '16 at 04:19
  • @JohnKugelman I just added an update that might help. Thanks for the comment after the downvote, it's actually refreshing to have decent feedback that might help improve the answer or my understanding of the problem. – Harry Apr 24 '16 at 04:40
  • 1
    I still don't agree. Bash is untyped, not dynamically typed. Everything in your answer is what makes it untyped. The fact that you can assign `WTF` and then increment it and Bash doesn't complain is a perfect example of being **untyped**. If it were typed in any way, be that dynamic or static, this wouldn't work. – John Kugelman Apr 24 '16 at 05:15
  • This is a nice, well-written answer. I hope you'll come around and update it to have the correct conclusion! – John Kugelman Apr 24 '16 at 05:16
  • @JohnKugelman The last edit demonstrates that Bash is typed ie `integer expression expected` is pretty clear that the language expects a particular type. – Harry Apr 24 '16 at 06:04
  • 3
    No, it means that `-eq` performs input validation on its arguments. That's not the same thing as typing. Typing implies type safety. That's the whole purpose of types, to add constraints to variables/values. Your `WTF` example demonstrates a *lack* of type safety. The string `WTF` is silently coerced into `0` when used in an arithmetic context. That's untyped behavior. – John Kugelman Apr 24 '16 at 06:10
  • Now `declare -i` *is* an example of typing. It tags the variable with extra meta-information and enforces type safety when the variable is used incorrectly. Unfortunately it's a very rarely used feature, and is also entirely optional. One is not required to use `declare -i` in order to perform arithmetic. Regular untyped string variables can be used just as easily. – John Kugelman Apr 24 '16 at 06:12
  • @JohnKugelman In my last example I don't use `declare` I just compare two variables. – Harry Apr 24 '16 at 06:15
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/110044/discussion-between-john-kugelman-and-harry). – John Kugelman Apr 24 '16 at 06:32
  • @Harry The context in which an expression exists, affects its interpretation by Bash. Take `((` for example. An arithmetic context, bounding an expression to a set of arithmetic rules ( and a bit more, to be exact. like the common `for ((i=0;i – Rany Albeg Wein Apr 24 '16 at 12:51
  • 1
    Moreover, even though `[` is a Bash built-in command, in the last line in your answer `foo.sh: line 5: [: abc: integer expression expected` it is `[` asking your for an integer expression. Again, a context which requires you to fit a set of rules. This is why, for example, `[[` is considered as a Bash *keyword*, which can do something like this `[[ foo = * ]]` using the `*` as a glob for string matching, unlike `[ foo = * ]` which will cause `*` to be expanded *before* the comparison is being executed. Sometimes Bash do takes control over expressions, but not in regard to type-saftey. – Rany Albeg Wein Apr 24 '16 at 13:01
  • @JohnKugelman: Your comments make sense to me. (1) Could you define "untyped" in general sense for programming languages? Is an untyped variable defined as a variable whose type can be changed implicitly according to the context? For a typed variable, can we change its type, and if yes, do we have to do it explicitly (like type conversion in C or C++)? (2) Is a "dynamically typed" variable defined as a variable whose type is not changeable implicitly (i.e. the variable is typed), and is determined dynamically at run time? – Tim Apr 24 '16 at 17:35
-1

Bash is a dynamically typed or more correctly it's a dynamically checked language. I've already added a long answer, this is the short one.

#!/bin/bash
arg1=1234
arg2=abc

if [ $arg1 -eq $arg2 ]; then
  echo "wtf";
fi

gives this error message....

foo.sh: line 5: [: abc: integer expression expected

The fact I have an error that tells me I have in some way made a mistake with regards type means something is checking types.

Harry
  • 11,298
  • 1
  • 29
  • 43
  • 2
    If `bash` were dynamically typed, it wouldn't *need* `-eq`; it could infer from the arguments if `=` should perform string or integer comparison. – chepner Apr 24 '16 at 14:01
  • Thanks, Harry. I have upvoted your replies. – Tim Apr 24 '16 at 17:28