I'm most of the way through updating the vim9.txt help, with only the last few subsections of Section 2 to go now, and have gotten stuck on this truthiness table in the "For the "??" operator" paragraph. It reads:
type truthy when ~
bool true, v:true or 1
number non-zero
float non-zero
string non-empty
blob non-empty
list non-empty (different from JavaScript)
tuple non-empty (different from JavaScript)
dictionary non-empty (different from JavaScript)
func when there is a function name
special true or v:true
job when not NULL
channel when not NULL
class when not NULL
object when not NULL (TODO: when isTrue() returns true)
The following types are all correct as documented: bool, number, float, string, blob, list, tuple, dictionary, func, job, and channel. Issues are with these:
class: "when not NULL" is incorrect because this type is never truthy. Trying to use a class to test for truthiness gives E1421: Class "Class" cannot be used as a value. The exception is null_class, though it is falsy anyhow (:vim9cmd echo null_class ?? 'falsy'). I think it should be removed from the list and moved to the notes covering the types that have no possible truthiness.object: "when not NULL" is incorrect because it appears that, currently at least, all objects are falsy. So, this is either a documentation mistake requiring correction or its a bug. (Also, should, "(TODO: when isTrue() returns true)" be removed?)special: This is not a type per se. There is the none type (v:t_none), which is falsy only, though. So, I think it would be better to remove special and instead include none in a note covering the types which have no possible truthiness.For completeness, these should also either be included in the list or covered in my proposed note:
enum: This is the same as class, never truthy, gives E1421 (though without null_enum existing it is slightly different to class).enumvalue: An enum value, whether initialised or not, is falsy. Whether that's intentional, and an initialised enum should be truthy, I don't know, though with it currently "never truthy", that aligns with the similar object type.typealias: Gives E1421, so should just be added to the "never truthy" note.Note/Particularly: There is a distinction between:
class, enum, typealias) ... E1421object, enumvalue) ... are these special cases or a bug?The following script illustrates these points.
vim9script
def Ftruthy(t: any, f: any): list<any>
return [t, !t ?? 'truthy', f, f ?? 'falsy']
enddef
# These working as documented
# ---------------------------
echo 'Primitives, like number (type 0), work as documented:'
echo Ftruthy(9, 0)
echo ' '
echo 'Collections, like list (type 3), work as documented:'
echo Ftruthy([9], null_list)
echo ' '
echo 'Funcref (type 2) works as documented:'
var F = (x) => x
echo Ftruthy(F, null_function)
echo ' '
echo 'Job (type 8) works as documented:'
var Job = job_start(['echo', 'test'])
echo Ftruthy(Job, null_job)
Job = null_job
# Class and object
# ----------------
echo ' '
echo 'Class (type 12) gives E1421: '
class Class
var x: number
endclass
try
echo Ftruthy(Class, null_class)
catch
echo v:exception # E1421: Class "Class" cannot be used as a value
finally
echo ' '
echo 'Object (type 13) is never truthy, including when not null: '
var o1 = Class.new(5)
var o2 = null_object
echo Ftruthy(o1, o2)
endtry
# Enum and enumvalue
# ------------------
echo ' '
echo 'Enum (type 15) gives E1421: '
enum Enum
Placeholder
endenum
try
echo Ftruthy(Enum, null_class) # There is no null_enum...using null_class
catch
echo v:exception # E1421: Enum "Enum" cannot be used as a value
finally
echo ' '
echo 'Enum value (type 16) is never truthy, including when not null: '
var e1 = Enum.Placeholder
var e2: Enum # uninitialized enum value == null (echo e2 == null ... true)
echo Ftruthy(e1, e2)
endtry
And the output:
image.png (view on web)
—
Reply to this email directly, view it on GitHub.
You are receiving this because you are subscribed to this thread.![]()
[Edits: fixed for my mistake surrounding E1405/E1421, which are only given when using Class/Enum as a value; ?? does not error with them, so the script to illustrate the point has been adjusted accordingly.]
My key question remains, i.e., Should types 12 to 16 be truthy when not null?; @chrisbra - perhaps you know the answer to this? My presumption is that it is unintentional/an oversight, so a bug, especially given the documentation currently promises that non-null Class and Object variables should be truthy, "when not NULL".
—
Reply to this email directly, view it on GitHub.
You are receiving this because you are subscribed to this thread.![]()
I would defer to @yegappan for this one please
—
Reply to this email directly, view it on GitHub.
You are receiving this because you are subscribed to this thread.![]()
@kennypete A class, enum, or typealias cannot be used as a value, so the help text should be updated to reflect that. I'll raise a PR to ensure we return true for non-null objects and enum values.
—
Reply to this email directly, view it on GitHub.
You are receiving this because you are subscribed to this thread.![]()
@kennypete A class, enum, or typealias cannot be used as a value, so the help text should be updated to reflect that. I'll raise a PR to ensure we return true for non-null objects and enum values.
Thanks @yegappan - I presumed object and enumvalue were/are wrong, so a PR for them sounds good.
Regarding class, enum, and typealias, though, initially they tripped me up because it's common to get, "cannot be used as a value", errors. Thing is though, as my script, above, shows, they can be tested, without error, with ?? in a script-local scope. In that case, they are always falsy, regardless of whether they are null. Focusing on those only, and showing ! too:
vim9script
echo '---null_class---'
echo 'null_class'
echo null_class ?? 'unknown class' # echos 'unknown class', as expected
echo '---class---'
class MyClass
endclass
echo MyClass ?? 'unknown class' # echos 'unknown class', but it's not null
echo !MyClass # echos true (falsy), which does not make sense?
echo '---typealias---'
type LB = list<bool>
echo LB ?? 'unknown typealias' # echos 'unknown typealias', but it's not null
echo !LB # echos true (falsy), which does not make sense?
echo '---enum---'
enum MyEnum
endenum
echo MyEnum ?? 'unknown enum' # echos 'unknown enum', but it's not null
echo !MyEnum # echos true (falsy), which does not make sense?
This script shows that these types can be tested with ?? and ! operators without error. So, they are usable as values in boolean script-local contexts, yet they are always falsy, even when not null. Given the general rule is "truthy when neither empty nor null", shouldn't MyClass, LB, and MyEnum be truthy in this context?
—
Reply to this email directly, view it on GitHub.
You are receiving this because you are subscribed to this thread.![]()
@kennypete A class, enum, or typealias cannot be used as a value, so the help text should be updated to reflect that. I'll raise a PR to ensure we return true for non-null objects and enum values.
Thanks @yegappan - I presumed object and enumvalue were/are wrong, so a PR for them sounds good.
Regarding class, enum, and typealias, though, initially they tripped me up because it's common to get, "cannot be used as a value", errors. Thing is though, as my script, above, shows, they can be tested, without error, with
??in a script-local scope. In that case, they are always falsy, regardless of whether they are null. Focusing on those only, and showing!too:
I have opened the PR #19216 to address this. Now class, enum
and typealiases cannot be used with the falsy operator.
—
Reply to this email directly, view it on GitHub.
You are receiving this because you are subscribed to this thread.![]()
I have opened the PR #19216 to address this. Now class, enum and typealiases cannot be used with the falsy operator.
Thanks, that feels like the right call, with the minor backwards incompatibility issue if anyone actually has used ?? or ! with a class, enum, or typealias in practice, which feels improbable.
PR #19216, and one to ensure non-null object and enumvalue variables are truthy, will make everything consistent.
—
Reply to this email directly, view it on GitHub.
You are receiving this because you are subscribed to this thread.![]()
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.![]()
Hi @yegappan, I checked out 9.1.2096 and 9.1.2101 and found the former fixes object/enumvalue, which are now truthy when not null, but the latter is not only erroring on class/enum/typealias (which is right) but it is also being evaluated when used with the falsy operator. A script and output to illustrate:
vim9script
echo v:versionlong # 9012101
class C
endclass
echo C ?? false
image.png (view on web)
—
Reply to this email directly, view it on GitHub.
You are receiving this because you are subscribed to this thread.![]()
Hi @yegappan, I checked out 9.1.2096 and 9.1.2101 and found the former fixes object/enumvalue, which are now truthy when not null, but the latter is not only erroring on class/enum/typealias (which is right) but it is also being evaluated when used with the falsy operator. A script and output to illustrate:
vim9script echo v:versionlong # 9012101 class C endclass echo C ?? false
It's similar for enum and typealias too.
I have opened the PR #19238 to abort the expression evaluation when a class or enum or a type alias is used as a value.
—
Reply to this email directly, view it on GitHub.
You are receiving this because you are subscribed to this thread.![]()
I have opened the PR #19238 to abort the expression evaluation when a class or enum or a type alias is used as a value.
Thanks, that should close the loose end.
Incidentally, now that class can't be used as a value in any context (E1405), does null_class serve any purpose? Before patch 9.1.2101, it had one theoretical use case (that is, if a non-null class had been "fixed" to be evaluated as truthy, null_class would have been falsy). I can't think what it would/could be used for now, though.
A similar question does not apply to the other two because there is neither null_enum nor null_typealias (not that it would make sense anyway).
—
Reply to this email directly, view it on GitHub.
You are receiving this because you are subscribed to this thread.![]()
I have opened the PR #19238 to abort the expression evaluation when a class or enum or a type alias is used as a value.
Thanks, that should close the loose end.
Incidentally, now that
classcan't be used as a value in any context (E1405), doesnull_classserve any purpose? Before patch 9.1.2101, it had one theoretical use case (that is, if a non-null class had been "fixed" to be evaluated as truthy,null_classwould have been falsy). I can't think what it would/could be used for now, though.A similar question does not apply to the other two because there is neither
null_enumnornull_typealias(not that it would make sense anyway).
The null_class is useful for testing the Vim9 class functionality with a null pointer for the class.
—
Reply to this email directly, view it on GitHub.
You are receiving this because you are subscribed to this thread.![]()
The
null_classis useful for testing the Vim9 class functionality with a null pointer for the class.
Sorry, this will be my last query about this...
I grepped the C source for null_class usage and found this in typval.c (line 1789):
// TODO: null_class handling // case VAR_CLASS: return tv->vval.v_class == NULL;
That commented null comparison handling would now be contradictory given null_class == {anything} gives E1405, so the comment there could be updated.
The only actual usage appears to be instanceof(null_object, null_class). Testing shows null_object is only an instance of null_class (and never an instance of an actual class), making this equivalent to obj == null_object, i.e., potentially redundant.
Unlike other null_* values, which serve clear purposes (uninitialized containers, etc.), null_class appears to exist only so testing can verify it produces errors, so it is circular. Is there practical null pointer testing I'm missing, or was this planned, left incomplete, and now unnecessary?
There is also testdir/test_vim9_disassemble.vim, which has var nc = null_class, showing null_class had been expected to be used as a value? It's also problematic because now the compilation will succeed, and disassembly shows likewise, but at runtime it's E1405, e.g.:
—
Reply to this email directly, view it on GitHub.
You are receiving this because you are subscribed to this thread.![]()