Frimaire / yags-lang

Yet Another Glue Script (YAGS) - Not only python with braces!
Apache License 2.0
1 stars 0 forks source link

Proposal Implicit Boolean Type Conversion #2

Open Frimaire opened 5 months ago

Frimaire commented 5 months ago

Implicit Boolean Type Conversion

Background

Currently, YAGS requires boolean expressions (such as the ! and ?: operators, conditions for if and while) must be boolean type (bool), otherwise a TypeError will be thrown. Avoiding implicit boolean conversions is a recommended coding practice in many places and is enforced in some languages (e.g. Java and Dart).

However, the rule against implicit boolean conversions doesn't quite fit in Python, which actually has more than one boolean type. Many libraries define their own Boolean types. For example, Numpy has its own boolean type:

var A = numpy.ones([1]);
// returns <class 'numpy.bool_'>
type(A[0] == 1)
type(A[0] > 0)
type(A.any())
type(A.all())
type(ones([1], bool)[0])

It is not feasible to simply treat numpy.bool_ as a special case. Because in addition to numpy, there are other modules that define their own Boolean types, such as PyTorch using a boolean tensor type. It is impossible to consider all cases of custom boolean types.

Proposal

For Boolean expression o, the following rules are used for Boolean type conversion:

  1. If o is a bool, return o.

  2. If o has a __bool__ member:

    1. If o.__bool__ is not callable, a TypeError is thrown.
    2. Let r = o.__bool__().
    3. If an exception occurs during the call, the exception is thrown.
    4. If r is not a bool, a TypeError is thrown.
    5. Return r.
  3. Otherwise, return true (True).

The difference from Python's own conversion rules is that the __len__ method will not be called here. This means that zero-length containers (e.g. arrays, tuples) will no longer be treated as falsy values.

Special Circumstances

NaN

Question: Should NaN be falsy?

It seems that only js treats NaN as falsy. Python, C, and PHP all treat NaN as a truthy value.

If this is necessary, this rule will only be effective for Python's built-in float, and this will not affect NaN with other types such as numpy.float64. At the same time, it needs to consider the situation where only the real part or the imaginary part of the complex number type is NaN.

Empty string

Question: Should an empty string be falsy?

In js, empty strings are considered falsy, but empty objects of type "object" such as empty arrays are truthy.

Despite this feature troubles developers who are not familiar with js, this issue may be less controversial. Also, Python's two types of strings (string and bytes) should be converted according to the same rules.

隐式布尔类型转换

背景

目前,YAGS要求布尔表达式(例如!?:运算符,ifwhile的条件)必须是布尔类型(bool),不然将抛出TypeError异常。避免隐式布尔类型转换在许多地方是一种推荐的编码规范,并在一些语言中(例如Java和Dart)被强制实施。

尽管如此,禁止隐式布尔类型转换的规则不太适合Python,因为Python实际上有不止一个布尔类型。许多库都会定义自身的布尔类型,例如Numpy就有自身的布尔类型:

var A = numpy.ones([1]);
// 全是<class 'numpy.bool_'>
type(A[0] == 1)
type(A[0] > 0)
type(A.any())
type(A.all())
type(ones([1], bool)[0])

单纯将numpy.bool_作为特殊情况考虑是不可行的。因为除了numpy之外,还有其他模块定义了自身的布尔类型,比如PyTorch使用张量布尔类型。不可能穷尽所有自定义布尔类型的情况。

计划

对于布尔表达式o,采用以下规则进行布尔类型转换:

  1. 如果o是布尔类型(bool),返回o

  2. 如果o具有__bool__成员:

    1. 如果o.__bool__不是可调用的,拋出TypeError异常。
    2. r = o.__bool__()
    3. 如果在调用过程中产生了异常,则抛出该异常。
    4. 如果r不是bool,拋出TypeError异常。
    5. 返回r
  3. 对于其他情况,返回trueTrue)。

和Python自身的转换规则区别在于,这里不会访问__len__方法。这意味着长度为零的容器(如数组、元组)将不再视为falsy值。

有关特殊情况

NaN

问题: NaN应当被认为是falsy吗?

似乎只有js才把NaN当成falsy。Python,C,PHP都把NaN当成truthy值。

如果需要此规则,此规则只会对Python内部的float有效,其他类型(比如numpy.float64)产生的NaN等是不会改变的。同时,如果实施此规则还需要考虑复数类型中,只有实部或虚部是NaN的情况。

空字符串

问题: 空字符串应当被认为是falsy吗?

在js中,空字符串被视为falsy,但是空数组等"object"类型的空对象是truthy。

除了让不熟悉js的开发者感到困扰外,这个问题可能争议会比较小。Python的两种字符串(stringbytes)应按相同的规则进行转换。

Frimaire commented 5 months ago

Currently, experimental implicit boolean conversion can be enabled with the compiler flag --enable-implicit-bool. Please note that "" converts to true and NaN converts to true.


目前实验性的隐式布尔类型转换可以通过编译器参数--enable-implicit-bool开启。 请注意空字符串和NaN均会转换为true