Index: doc/Announce2.3.0 =================================================================== diff -u -r63fa317128555211b749beedd51f32e82af6b340 -rfc11b2380eef48346410636908936e9468c74807 --- doc/Announce2.3.0 (.../Announce2.3.0) (revision 63fa317128555211b749beedd51f32e82af6b340) +++ doc/Announce2.3.0 (.../Announce2.3.0) (revision fc11b2380eef48346410636908936e9468c74807) @@ -50,6 +50,30 @@ - NX: + * Properties and variables now provide "exists" as an additional + accessor method, in addition to "get": + + % package req nx + 2.3 + % nx::Class create C { + :property -accessor public {a 1} + } + ::C + % ::C create ::c1 + ::c1 + % if {[::c1 a exists]} { ::c1 a get } else { ::c1 a set "1" } + ^^^^^^ + + This is mainly to provide for symmetry in the property and + variable API, which otherwise requires one to resort to low-level + tests for existence, e.g.: + + if {[::c1 eval {info exists :a}]} ... + + This breaks the property/ variable abstraction, because one cannot + move to a different value store other than object variables w/o + rewriting client code. + * Method combination for ensemble methods: Using [next] at the end of chains of ensemble methods fired the unknown handler, unintentionally. This was fixed. Index: doc/Class.3 =================================================================== diff -u -rbaee0c34119f4b237787204b8c3e64bc04c05782 -rfc11b2380eef48346410636908936e9468c74807 --- doc/Class.3 (.../Class.3) (revision baee0c34119f4b237787204b8c3e64bc04c05782) +++ doc/Class.3 (.../Class.3) (revision fc11b2380eef48346410636908936e9468c74807) @@ -2,7 +2,7 @@ '\" Generated from file 'Class\&.man' by tcllib/doctools with format 'nroff' '\" Copyright (c) 2014-2016 Stefan Sobernig , Gustaf Neumann ; available under the Creative Commons Attribution 3\&.0 Austria license (CC BY 3\&.0 AT)\&. '\" -.TH "nx::Class" 3 2\&.3a0 Class "NX API" +.TH "nx::Class" 3 2\&.3 Class "NX API" .\" The -*- nroff -*- definitions below are for supplemental macros used .\" in Tcl/Tk manual entries. .\" @@ -955,10 +955,14 @@ which become assigned to the property\&. The second, optional element sets a \fIdefaultValue\fR for this property\&. .sp -If \fB-accessor\fR is set, a property will provide for -a pair of getter and setter methods: +If \fB-accessor\fR is set, a property will provide for different +getter and setter methods: .RS .TP +\fIobj\fR \fIpropertyName\fR \fBexists\fR +Returns 1 if the value store of \fIpropertyName\fR (e\&.g\&., an object +variable) exists and has been given a value, returns 0 otherwise\&. +.TP \fIobj\fR \fIpropertyName\fR \fBset\fR \fIvalue\fR Sets the property \fIpropertyName\fR to \fIvalue\fR\&. .TP @@ -1063,10 +1067,14 @@ managed by the variable\&. Optionally, a \fIdefaultValue\fR can be defined\&. .sp -If \fB-accessor\fR is set explicitly, a variable will provide for a pair of -getter and setter methods: +If \fB-accessor\fR is set explicitly, a variable will +provide for getter and setter methods: .RS .TP +\fIobj\fR \fIvariableName\fR \fBexists\fR +Returns 1 if the value store of \fIvariableName\fR (e\&.g\&., an object +variable) exists and has been given a value, returns 0 otherwise\&. +.TP \fIobj\fR \fIvariableName\fR \fBset\fR \fIvarValue\fR Sets \fIvariableName\fR to \fIvarValue\fR\&. .TP Index: doc/Object.3 =================================================================== diff -u -r6cbeef2d45ae090cf57de7703e0b480125e277b1 -rfc11b2380eef48346410636908936e9468c74807 --- doc/Object.3 (.../Object.3) (revision 6cbeef2d45ae090cf57de7703e0b480125e277b1) +++ doc/Object.3 (.../Object.3) (revision fc11b2380eef48346410636908936e9468c74807) @@ -1268,10 +1268,14 @@ which become assigned to the property\&. The second, optional element sets a \fIdefaultValue\fR for this property\&. .sp -If \fB-accessor\fR is set, a property will provide for -a pair of getter and setter methods: +If \fB-accessor\fR is set, a property will provide for different +getter and setter methods: .RS .TP +\fIobj\fR \fIpropertyName\fR \fBexists\fR +Returns 1 if the value store of \fIpropertyName\fR (e\&.g\&., an object +variable) exists and has been given a value, returns 0 otherwise\&. +.TP \fIobj\fR \fIpropertyName\fR \fBset\fR \fIvalue\fR Sets the property \fIpropertyName\fR to \fIvalue\fR\&. .TP @@ -1510,10 +1514,14 @@ managed by the variable\&. Optionally, a \fIdefaultValue\fR can be defined\&. .sp -If \fB-accessor\fR is set explicitly, a variable will provide for a pair of -getter and setter methods: +If \fB-accessor\fR is set explicitly, a variable will +provide for getter and setter methods: .RS .TP +\fIobj\fR \fIvariableName\fR \fBexists\fR +Returns 1 if the value store of \fIvariableName\fR (e\&.g\&., an object +variable) exists and has been given a value, returns 0 otherwise\&. +.TP \fIobj\fR \fIvariableName\fR \fBset\fR \fIvarValue\fR Sets \fIvariableName\fR to \fIvarValue\fR\&. .TP Index: doc/property.man.inc =================================================================== diff -u -r8f64a468d8bb53f2ba317c8c738c2d3a24243980 -rfc11b2380eef48346410636908936e9468c74807 --- doc/property.man.inc (.../property.man.inc) (revision 8f64a468d8bb53f2ba317c8c738c2d3a24243980) +++ doc/property.man.inc (.../property.man.inc) (revision fc11b2380eef48346410636908936e9468c74807) @@ -27,9 +27,12 @@ [para] -If [option "-accessor"] is set, a property will provide for -a pair of getter and setter methods: +If [option "-accessor"] is set, a property will provide for different +getter and setter methods: [list_begin definitions] +[def "[arg obj] [arg propertyName] [method exists]"] +Returns 1 if the value store of [arg propertyName] (e.g., an object +variable) exists and has been given a value, returns 0 otherwise. [def "[arg obj] [arg propertyName] [method set] [arg value]"] Sets the [term property] [arg propertyName] to [arg value]. [def "[arg obj] [arg propertyName] [method get]"] Index: doc/variable.man.inc =================================================================== diff -u -r8f64a468d8bb53f2ba317c8c738c2d3a24243980 -rfc11b2380eef48346410636908936e9468c74807 --- doc/variable.man.inc (.../variable.man.inc) (revision 8f64a468d8bb53f2ba317c8c738c2d3a24243980) +++ doc/variable.man.inc (.../variable.man.inc) (revision fc11b2380eef48346410636908936e9468c74807) @@ -18,10 +18,13 @@ [para] -If [option "-accessor"] is set explicitly, a [term variable] will provide for a pair of -getter and setter methods: +If [option "-accessor"] is set explicitly, a [term variable] will +provide for getter and setter methods: [list_begin definitions] +[def "[arg obj] [arg variableName] [method exists]"] +Returns 1 if the value store of [arg variableName] (e.g., an object +variable) exists and has been given a value, returns 0 otherwise. [def "[arg obj] [arg variableName] [method set] [arg varValue]"] Sets [arg variableName] to [arg varValue]. [def "[arg obj] [arg variableName] [method get]"] Index: library/nx/nx.tcl =================================================================== diff -u -r77a193c118f4ae2b0ccd0913e39326e4f0f53fe6 -rfc11b2380eef48346410636908936e9468c74807 --- library/nx/nx.tcl (.../nx.tcl) (revision 77a193c118f4ae2b0ccd0913e39326e4f0f53fe6) +++ library/nx/nx.tcl (.../nx.tcl) (revision fc11b2380eef48346410636908936e9468c74807) @@ -2273,6 +2273,10 @@ ::nsf::var::unset -nocomplain=$nocomplain $obj $prop } + ::nx::VariableSlot public method value=exists {obj prop} { + ::nsf::var::exists $obj $prop + } + ::nx::VariableSlot public method value=add {obj prop value {pos 0}} { if {![:isMultivalued]} { #puts stderr "... vars [[self] info vars] // [[self] eval {set :multiplicity}]" Index: tests/methods.test =================================================================== diff -u -r8e2e356e9bcef39f43dfe3690b82d9586c7adc72 -rfc11b2380eef48346410636908936e9468c74807 --- tests/methods.test (.../methods.test) (revision 8e2e356e9bcef39f43dfe3690b82d9586c7adc72) +++ tests/methods.test (.../methods.test) (revision fc11b2380eef48346410636908936e9468c74807) @@ -646,7 +646,7 @@ } # dispatch methods without current object - ? ::o::a {wrong # args: use "::o ::o::a add|delete|get|set|unset"} + ? ::o::a {wrong # args: use "::o ::o::a add|delete|exists|get|set|unset"} ? ::o::b "::o2" ? ::o::foo "no current object; command called outside the context of a Next Scripting method" ? ::o::x "no current object; x called outside the context of a Next Scripting method" Index: tests/properties.test =================================================================== diff -u -r8e2e356e9bcef39f43dfe3690b82d9586c7adc72 -rfc11b2380eef48346410636908936e9468c74807 --- tests/properties.test (.../properties.test) (revision 8e2e356e9bcef39f43dfe3690b82d9586c7adc72) +++ tests/properties.test (.../properties.test) (revision fc11b2380eef48346410636908936e9468c74807) @@ -11,7 +11,6 @@ #puts stderr "*** default defaultAccessor '[nx::configure defaultAccessor]'" nx::configure defaultAccessor none - ##################################################################### # class-level properties ##################################################################### @@ -788,7 +787,86 @@ ? {C cget -b} b2 } +nx::test case exists-on-props { + nx::Class create C { + :object property {A A1} + :property {a a1} + + :object property -accessor public {B B1} + :property -accessor public {b b1} + :object property -accessor public BB + :property -accessor public bb + :object property -accessor protected {C C1} + :property -accessor protected {c c1} + + :object property -accessor private {D D1} + :property -accessor private {d d1} + + :create c1 + + :public object method do {args} { + : {*}$args + } + + :public method do {args} { + : {*}$args + } + + :public object method doLocal {args} { + : -local {*}$args + } + + :public method doLocal {args} { + : -local {*}$args + } + + } + + ? {::C A exists} \ + "method 'A' unknown for ::C; in order to create an instance of class ::C, consider using '::C create A ?...?'" + ? {::c1 a exists} "::c1: unable to dispatch method 'a'" + + ? {::C B exists} 1 + ? {::c1 b exists} 1 + + ? {::C B get} "B1" + ? {::c1 b get} "b1" + + ? {::C BB exists} 0 + ? {::c1 bb exists} 0 + + ? {::C do C exists} 1 + ? {::C eval {info exists :C}} 1 + ? {::c1 do c exists} 1 + ? {::c1 eval {info exists :c}} 1 + + ? {::C do C unset} "" + ? {::c1 do c unset} "" + + ? {::C do C exists} 0 + ? {::C eval {info exists :C}} 0 + ? {::c1 do c exists} 0 + ? {::c1 eval {info exists :c}} 0 + + # interaction: exists + private + + ? {::C doLocal D exists} 1 + ? {::c1 doLocal d exists} 1 + + ? {::C doLocal D unset} "" + ? {::c1 doLocal d unset} "" + + ? {::C doLocal D exists} 0 + ? {::c1 doLocal d exists} 0 + + ? {::C D exists} \ + "method 'D' unknown for ::C; in order to create an instance of class ::C, consider using '::C create D ?...?'" + ? {::c1 d exists} "::c1: unable to dispatch method 'd'" + +} + + ##################################################################### # performance tests #####################################################################