在学习很多编程语言后,发现虽然大部分语言都支持变量声明,而且语义都一样,但是声明的语法却有很多种。正好近期也在设计这样的语法,就结合过去接触的语言来阐述自己的感想。
(虽然前面提到的都是变量声明,但是本文把常量声明、指针声明这类把值和名称关联的语法也一起讨论)
各个语言的变量声明方式并不影响程序运行时的效率,最多对语言处理程序的开发和执行有点影响,而变量声明方式的变化影响最大的其实是开发者阅读代码时的感受。因此,本文在讨论一种表达方式时,不考虑其对程序和语言处理程序的影响,仅从阅读的角度来谈论。(因为不同的人学习的第一个开发语言都可能不同,“母语”会对人接受新事物产生巨大影响,而开发经历和学过的语言也不同,理解也不同,所以难以做到客观评价,我也只能尽量“客观”地去分析了)
首先来看最为常见的Java的变量声明
int a;
int x = 1;
final int y = 2;
int[] nums = new int[10];
int nums2[] = {1,2,3,4,5};
List<Integer> numList = new LinkedList<>();
我们可以看到java语言里,等号前面的声明都把变量名放在最后,除了数组的声明有两种方式,一种是把[]
放在变量名称后面。这种把修饰变量的关键字全部放在名称前的表达,一致性比较高,即便以后语言扩展了,也可以在前面继续追加关键字。
至于缺点嘛,关键字长可能是一个吧(不过这也意味着信息表达地更全面一些),例如,你可以看到这样的声明:
private static final int x = 0;
另外,Java的类型声明中有两个“潜规则”:1. 类的成员变量中如果没有private/protected/public
修饰时则为包访问权限;2. 变量没有final
修饰时,可以被赋值。我个人主观上不太喜欢这类“潜规则”,虽然带来了一些便利,但是降低了一致性,而且如果其他语言在类似语法采用不同的“潜规则”,也给学习带来了一些麻烦。
接下来看一下相似的C语言的变量声明方式:
int x = 1;
int *p1;
const int x2 = 1;
int *const p = &x;
const int *const px = &x;
int nums[10];
emmm…看上去C语言和Java的表达有点像,但是指针的引入让变量的声明有一点点复杂了,毕竟“*”号的位置会决定这个符号对应的到底是常量指针还是指针常量,这个对新手还是有些麻烦的。类似的把修饰标识放在变量名前面的设计,主观上我更倾向于简单的规则,或者没有规则。
js的变量声明大概是最//常量
var x1 = 1;
let x2 = 2;
let a1 = 1, a2 = 2
const s = "asdf"
js的声明比较简单(虽然作用域并不简单),不过相对的也没法表达较复杂的变量信息。
Scala的变量声明有点不一样:
var x1 = 1
val x2 = 2
var x3: Int = 3
val x4: Int = 4
var x5: (Int, String) = (1, "hello")
var f1 = (x:Int, s:String) => {
return x + s.length
}
val f2:(Int, String) => String = (x, s) => {
x + " - " + s
}
val ints: List[Int] = List(1, 2, 3)
它将变量的类型放在名称后面,用冒号分隔,变量的可变性通过前面的var
和val
控制,而且因为scala支持类型推导,所以可以省略类型声明。但这也引入新的问题,就是什么时候应该声明类型?还有就是当等号两边表达式都比较长的时候,或者不止一个等号的时候,代码阅读起来会有些麻烦。
Python的变量声明有比较大的不同,
a = 100
PI = 3.14
class Student(object):
count = 0
def __init__(self, name, score):
self.__name = name
self.__score = score
Student.count += 1
python程序里等号的左侧除了名字没有任何修饰,是一种极简的表达,这使得程序看上去更加简洁,而通过命名来控制对象属性的访问限制也是一种实用的实现,既没有使程序变得过长,该表达的信息也都表达清楚了。不过这样对简洁的追求也导致了一些问题,声明和赋值合为一体后,变量的作用域有些模糊;另外追求简洁也就意味着无法增加过多的表达。
看了上面的一些实现大都专门用一个关键字来区分,例如:var
、val
、final
、const
等等,那么可不可以用赋值/关联符号来区分呢,比如:
int x = 1 //变量
int y : 2 //常量
等号用于变量,冒号用于常量,因为变量可以重新赋值,而常量不可以。
又或者利用变量名前后缀来表达:
int a = 1 //变量
int |x| = 1 //常量
int !x = 1 //常量
一般都将修饰变量的关键字放在前面,那么全部放在后面呢:
a = 1
a = 1
虽然看着有点怪,不过也看得过去。
后续更新