Index: Makefile.in =================================================================== diff -u -N -r17880e63ccb02577a5c856aaa6344cd83028a07b -r5693145107c55b5f64bf0fb487aa43e0f2238f1a --- Makefile.in (.../Makefile.in) (revision 17880e63ccb02577a5c856aaa6344cd83028a07b) +++ Makefile.in (.../Makefile.in) (revision 5693145107c55b5f64bf0fb487aa43e0f2238f1a) @@ -47,6 +47,7 @@ appdirs = appsrc = COPYRIGHT + # XOTcl subpackage xotcl_srcdir = ${srcdir}/library/xotcl xotcl_src_doc_dir = ${xotcl_srcdir}/doc @@ -222,6 +223,21 @@ # Start of user-definable TARGETS section #======================================================================== +EXAMPLE_SCRIPTS = \ + $(src_doc_dir)/example-scripts/bagel.html \ + $(src_doc_dir)/example-scripts/rosetta-classes.html \ + $(src_doc_dir)/example-scripts/rosetta-constraint-genericity.html \ + $(src_doc_dir)/example-scripts/rosetta-delegates.html \ + $(src_doc_dir)/example-scripts/rosetta-distinct-objects.html \ + $(src_doc_dir)/example-scripts/rosetta-polymorphic-copy.html \ + $(src_doc_dir)/example-scripts/rosetta-polymorphism.html \ + $(src_doc_dir)/example-scripts/rosetta-serialization.html \ + $(src_doc_dir)/example-scripts/rosetta-singleton.html \ + +%.html : %.tcl + $(TCLSH) $(src_app_dir_native)/utils/source-doc-beautifier.tcl $< + asciidoc $*.txt + #======================================================================== # TEA TARGETS. Please note that the "libraries:" target refers to platform # independent files, and the "binaries:" target inclues executable programs and @@ -254,10 +270,12 @@ libraries-pkgindex: pkgIndex.tcl @$(TCLSH) $(src_lib_dir_native)/lib/make.tcl -dir $(src_lib_dir_native) -all -fulldoc: doc pdf +full-doc: doc pdf example-doc # use language reference as sample file to trigger generation of documentation files doc: $(xotcl_target_doc_dir)/langRef-xotcl.html +example-doc: $(EXAMPLE_SCRIPTS) + $(xotcl_target_doc_dir)/langRef-xotcl.html: pkgIndex.tcl $(xotcl_src_doc_dir)/langRef.xotcl $(XODOC_SOURCE) @docs=""; \ for i in $(XODOC_SOURCE); do docs="$$docs `@CYGPATH@ $$i`"; done; \ @@ -415,6 +433,16 @@ $(TCLSH) $(src_test_dir_native)/mixinof.test -libdir $(PLATFORM_DIR) $(TESTFLAGS) $(TCLSH) $(src_test_dir_native)/tcl86.test -libdir $(PLATFORM_DIR) $(TESTFLAGS) $(TCLSH) $(src_test_dir_native)/contains.test -libdir $(PLATFORM_DIR) $(TESTFLAGS) + $(TCLSH) $(src_doc_dir_native)/example-scripts/bagel.tcl -libdir $(PLATFORM_DIR) $(TESTFLAGS) + $(TCLSH) $(src_doc_dir_native)/example-scripts/rosetta-singleton.tcl -libdir $(PLATFORM_DIR) $(TESTFLAGS) + $(TCLSH) $(src_doc_dir_native)/example-scripts/rosetta-classes.tcl -libdir $(PLATFORM_DIR) $(TESTFLAGS) + $(TCLSH) $(src_doc_dir_native)/example-scripts/rosetta-constraint-genericity.tcl -libdir $(PLATFORM_DIR) $(TESTFLAGS) + $(TCLSH) $(src_doc_dir_native)/example-scripts/rosetta-delegates.tcl -libdir $(PLATFORM_DIR) $(TESTFLAGS) + $(TCLSH) $(src_doc_dir_native)/example-scripts/rosetta-distinct-objects.tcl -libdir $(PLATFORM_DIR) $(TESTFLAGS) + $(TCLSH) $(src_doc_dir_native)/example-scripts/rosetta-polymorphic-copy.tcl -libdir $(PLATFORM_DIR) $(TESTFLAGS) + $(TCLSH) $(src_doc_dir_native)/example-scripts/rosetta-polymorphism.tcl -libdir $(PLATFORM_DIR) $(TESTFLAGS) + $(TCLSH) $(src_doc_dir_native)/example-scripts/rosetta-serialization.tcl -libdir $(PLATFORM_DIR) $(TESTFLAGS) + $(TCLSH) $(src_doc_dir_native)/example-scripts/rosetta-singleton.tcl -libdir $(PLATFORM_DIR) $(TESTFLAGS) test-xotcl: $(TCLSH_PROG) $(TCLSH) $(xotcl_src_test_dir)/testo.xotcl -libdir $(PLATFORM_DIR) $(TESTFLAGS) Index: TODO =================================================================== diff -u -N -rca508a05de8e3783d432b8de2db2ae3e61ae271e -r5693145107c55b5f64bf0fb487aa43e0f2238f1a --- TODO (.../TODO) (revision ca508a05de8e3783d432b8de2db2ae3e61ae271e) +++ TODO (.../TODO) (revision 5693145107c55b5f64bf0fb487aa43e0f2238f1a) @@ -3302,7 +3302,12 @@ * removed the nonpos argument "-incremental" from "property" and "variable" * adapted regression test for these cases +- new folder example-scripts + * Added 8 of the rosetta examples and one classical OTcl example + * all examples are tested via regression test + * all examples are pretty-printed via asciidoc + TODO: - nx: * maybe provide a replacement for -attributes, but without the magic variable. Index: doc/example-scripts/bagel.html =================================================================== diff -u -N --- doc/example-scripts/bagel.html (revision 0) +++ doc/example-scripts/bagel.html (revision 5693145107c55b5f64bf0fb487aa43e0f2238f1a) @@ -0,0 +1,1091 @@ + + + + + +Listing of doc/example-scripts/bagel.tcl + + + + + +
+
+
+

This example is a straight translation of the OTcl Tutorial +http://www.isi.edu/nsnam/otcl/doc/tutorial.html to NX. It serves as +a very short intro to the basic elements of scripting with NX and +provides a comparison study to OTcl.

+
+
+
package req nx
+

Suppose we need to work with many bagels in our application. We +might start by creating a Bagel class.

+
+
+
% nx::Class create Bagel
+::Bagel
+

We can now create bagels and keep track of them using the info +method.

+
+
+
% Bagel create abagel
+::abagel
+
+% abagel info class
+::Bagel
+
+% Bagel info instances
+::abagel
+

Of course, bagels don’t do much yet. They should remember whether +they’ve been toasted. We can create and access an instance variable +by defining an property for the class. All instance variables are +per default public in the sense of C++.

+
+
+
% Bagel property {toasted 0}
+::nsf::classes::Bagel::toasted
+

Since abagel was created before the definition of the property we +have to set the default value for it using the setter method. Again, +the info method helps us keep track of things.

+
+
+
% abagel toasted 0
+0
+
+% abagel info vars
+toasted
+
+% abagel toasted
+0
+

But we really want them to begin in an untoasted state to start +with.

+
+
+
% Bagel create bagel2
+::bagel2
+
+% bagel2 info vars
+toasted
+
+% bagel2 toasted
+0
+

Our bagels now remember whether they’ve been toasted. Let is +recreate the first one.

+
+
+
% lsort [Bagel info instances]
+::abagel ::bagel2
+
+% ::abagel destroy
+
+% Bagel info instances
+::bagel2
+
+% Bagel create abagel
+::abagel
+

Now we’re ready to add a method to bagels so that we can toast +them. Methods have an argument list and body like regular +Tcl procs. Here’s the toast method.

+
+
+
% Bagel public method toast {} {
+      if {[incr :toasted]>1} then {
+        error "something's burning!"
+      }
+}
+::nsf::classes::Bagel::toast
+

The defined methods can be queried with info. We see as well the +setter method for the variable toasted.

+
+
+
% Bagel info methods
+toasted toast
+

Aside from setting the toasted variable, the body of the toast +method demonstrates how to access instance variables by using a +leading colon in the name.

+

We invoke the toast method on bagels in the same way we use the +info and destroy methods that were provided by the system. That +is, there is no distinction between user and system methods.

+
+
+
% abagel toast
+% abagel toast
+something's burning!
+

Now we can add spreads to the bagels and start tasting them. If we +have bagels that aren’t topped, as well as bagels that are, we may +want to make toppable bagels a separate class. Let explore +inheritance with these two classes, starting by making a new class +SpreadableBagel that inherits from Bagel. A SpreadableBagel has an +property toppings which might have multiple values. Initially, +toppings are empty.

+
+
+
% nx::Class create SpreadableBagel -superclass Bagel {
+    :property {toppings:0..n ""}
+}
+::SpreadableBagel
+
+% SpreadableBagel info superclass
+::Bagel
+
+% SpreadableBagel info heritage
+::Bagel ::nx::Object
+

Let’s add a taste method to bagels, splitting its functionality +between the two classes and combining it with next.

+
+
+
% Bagel public method taste {} {
+    if {${:toasted} == 0} then {
+    return raw!
+  } elseif {${:toasted} == 1} then {
+    return toasty
+  } else {
+    return burnt!
+  }
+}
+::nsf::classes::Bagel::taste
+
+% SpreadableBagel public method taste {} {
+    set t [next]
+    foreach i ${:toppings} {
+       lappend t $i
+    }
+    return $t
+}
+::nsf::classes::SpreadableBagel::taste
+
+% SpreadableBagel create abagel
+::abagel
+
+% abagel toast
+% abagel toppings jam
+jam
+
+% abagel taste
+toasty jam
+

Of course, along come sesame, onion, poppy, and a host of other +bagels, requiring us to expand our scheme. We could keep track of +flavor with an instance variable, but this may not be +appropriate. Flavor is an innate property of the bagels, and one +that can affect other behavior - you wouldn’t put jam on an onion +bagel, would you? Instead of making a class hierarchy, let’s use +multiple inheritance to make the flavor classes mixins that add a +their taste independent trait to bagels or whatever other food they +are mixed with.

+
+
+
% nx::Class create Sesame {
+    :public method taste {} {concat [next] "sesame"}
+}
+::Sesame
+
+% nx::Class create Onion {
+    :public method taste {} {concat [next] "onion"}
+}
+::Onion
+
+% nx::Class create Poppy {
+    :public method taste {} {concat [next] "poppy"}
+}
+::Poppy
+

Well, they don’t appear to do much, but the use of next allows them +to be freely mixed.

+
+
+
% nx::Class create SesameOnionBagel -superclass SpreadableBagel -mixin {Sesame Onion}
+::SesameOnionBagel
+
+% SesameOnionBagel create abagel -toppings butter
+::abagel
+
+% abagel taste
+raw! butter onion sesame
+

For multiple inheritance, the system determines a linear inheritance +ordering that respects all of the local superclass orderings. You +can examine this ordering with an info option. next follows this +ordering when it combines behavior.

+
+
+
% SesameOnionBagel info heritage
+::Sesame ::Onion ::SpreadableBagel ::Bagel ::nx::Object
+
+% abagel info precedence
+::Sesame ::Onion ::SesameOnionBagel ::SpreadableBagel ::Bagel ::nx::Object
+

We can also combine our mixins with other classes, classes that need +have nothing to do with bagels, leading to a family of chips.

+
+
+
% nx::Class create Chips {
+    :public method taste {} {return "crunchy"}
+}
+::Chips
+
+% nx::Class create OnionChips -superclass Chips -mixin Onion
+::OnionChips
+
+% OnionChips create abag
+::abag
+
+% abag taste
+crunchy onion
+
+
+
+

+ + + Index: doc/example-scripts/bagel.tcl =================================================================== diff -u -N --- doc/example-scripts/bagel.tcl (revision 0) +++ doc/example-scripts/bagel.tcl (revision 5693145107c55b5f64bf0fb487aa43e0f2238f1a) @@ -0,0 +1,185 @@ +# +# This example is a straight translation of the OTcl Tutorial +# http://www.isi.edu/nsnam/otcl/doc/tutorial.html to NX. It serves as +# a very short intro to the basic elements of scripting with NX and +# provides a comparison study to OTcl. +# + +package req nx +package req nx::test +nx::Test parameter count 1 + +# Suppose we need to work with many bagels in our application. We +# might start by creating a Bagel class. + +? {nx::Class create Bagel} ::Bagel + +# We can now create bagels and keep track of them using the info +# method. + +? {Bagel create abagel} ::abagel + +? {abagel info class} ::Bagel + +? {Bagel info instances} ::abagel + +# Of course, bagels don't do much yet. They should remember whether +# they've been toasted. We can create and access an instance variable +# by defining an property for the class. All instance variables are +# per default public in the sense of C++. +? {Bagel property {toasted 0}} "::nsf::classes::Bagel::toasted" + +# Since abagel was created before the definition of the property we +# have to set the default value for it using the setter method. Again, +# the info method helps us keep track of things. + +? {abagel toasted 0} 0 + +? {abagel info vars} toasted + +? {abagel toasted} 0 + +# But we really want them to begin in an untoasted state to start +# with. + +? {Bagel create bagel2} ::bagel2 + +? {bagel2 info vars} toasted + +? {bagel2 toasted} 0 + +# +# Our bagels now remember whether they've been toasted. Let is +# recreate the first one. + +? {lsort [Bagel info instances]} {::abagel ::bagel2} + +? {::abagel destroy} "" + +? {Bagel info instances} ::bagel2 + +? {Bagel create abagel} ::abagel + +# Now we're ready to add a method to bagels so that we can toast +# them. Methods have an argument list and body like regular +# Tcl procs. Here's the toast method. + +? {Bagel public method toast {} { + if {[incr :toasted]>1} then { + error "something's burning!" + } +}} "::nsf::classes::Bagel::toast" + +# The defined methods can be queried with info. We see as well the +# setter method for the variable toasted. + +? {Bagel info methods} {toasted toast} + +# Aside from setting the toasted variable, the body of the toast +# method demonstrates how to access instance variables by using a +# leading colon in the name. + +# We invoke the toast method on bagels in the same way we use the +# info and destroy methods that were provided by the system. That +# is, there is no distinction between user and system methods. + +? {abagel toast} "" +? {abagel toast} "something's burning!" + +# Now we can add spreads to the bagels and start tasting them. If we +# have bagels that aren't topped, as well as bagels that are, we may +# want to make toppable bagels a separate class. Let explore +# inheritance with these two classes, starting by making a new class +# SpreadableBagel that inherits from Bagel. A SpreadableBagel has an +# property toppings which might have multiple values. Initially, +# toppings are empty. + +? {nx::Class create SpreadableBagel -superclass Bagel { + :property {toppings:0..n ""} +}} ::SpreadableBagel + +? {SpreadableBagel info superclass} ::Bagel + +? {SpreadableBagel info heritage} {::Bagel ::nx::Object} + +# Let's add a taste method to bagels, splitting its functionality +# between the two classes and combining it with next. + +? {Bagel public method taste {} { + if {${:toasted} == 0} then { + return raw! + } elseif {${:toasted} == 1} then { + return toasty + } else { + return burnt! + } +}} "::nsf::classes::Bagel::taste" + +? {SpreadableBagel public method taste {} { + set t [next] + foreach i ${:toppings} { + lappend t $i + } + return $t +}} "::nsf::classes::SpreadableBagel::taste" + +? {SpreadableBagel create abagel} ::abagel + +? {abagel toast} "" +? {abagel toppings jam} jam + +? {abagel taste} "toasty jam" + +# Of course, along come sesame, onion, poppy, and a host of other +# bagels, requiring us to expand our scheme. We could keep track of +# flavor with an instance variable, but this may not be +# appropriate. Flavor is an innate property of the bagels, and one +# that can affect other behavior - you wouldn't put jam on an onion +# bagel, would you? Instead of making a class hierarchy, let's use +# multiple inheritance to make the flavor classes mixins that add a +# their taste independent trait to bagels or whatever other food they +# are mixed with. + +? {nx::Class create Sesame { + :public method taste {} {concat [next] "sesame"} +}} ::Sesame + +? {nx::Class create Onion { + :public method taste {} {concat [next] "onion"} +}} "::Onion" + +? {nx::Class create Poppy { + :public method taste {} {concat [next] "poppy"} +}} "::Poppy" + +# Well, they don't appear to do much, but the use of next allows them +# to be freely mixed. + +? {nx::Class create SesameOnionBagel -superclass SpreadableBagel -mixin {Sesame Onion}} ::SesameOnionBagel + +? {SesameOnionBagel create abagel -toppings butter} "::abagel" + +? {abagel taste} "raw! butter onion sesame" + +# For multiple inheritance, the system determines a linear inheritance +# ordering that respects all of the local superclass orderings. You +# can examine this ordering with an info option. next follows this +# ordering when it combines behavior. + +? {SesameOnionBagel info heritage} {::Sesame ::Onion ::SpreadableBagel ::Bagel ::nx::Object} + +? {abagel info precedence} {::Sesame ::Onion ::SesameOnionBagel ::SpreadableBagel ::Bagel ::nx::Object} + +# We can also combine our mixins with other classes, classes that need +# have nothing to do with bagels, leading to a family of chips. + +? {nx::Class create Chips { + :public method taste {} {return "crunchy"} +}} "::Chips" + +? {nx::Class create OnionChips -superclass Chips -mixin Onion} ::OnionChips + +? {OnionChips create abag} ::abag + +? {abag taste} "crunchy onion" + Index: doc/example-scripts/rosetta-classes.html =================================================================== diff -u -N --- doc/example-scripts/rosetta-classes.html (revision 0) +++ doc/example-scripts/rosetta-classes.html (revision 5693145107c55b5f64bf0fb487aa43e0f2238f1a) @@ -0,0 +1,791 @@ + + + + + +Listing of doc/example-scripts/rosetta-classes.tcl + + + + + +
+
+

Rosetta Example: Classes

+
+ +
+
+
package req nx
+
+nx::Class create summation {
+  :method init {} {set :v 0}
+  :public method add {x} {incr :v $x}
+  :public method value {} {return ${:v}}
+  :public method destroy {} {puts "ended with value [:value]"; next}
+}
+
+

Demonstrating the behavior in a shell:

+
+
+
% set sum [summation new]
+% $sum value
+0
+% $sum add 1
+1
+% $sum add 2
+3
+% $sum add 3
+6
+% $sum add 4
+10
+% $sum value
+10
+

During the destroy of the object, ended with value 10 is printed

+
+
+
% $sum destroy
+
+
+
+
+

+ + + Index: doc/example-scripts/rosetta-classes.tcl =================================================================== diff -u -N --- doc/example-scripts/rosetta-classes.tcl (revision 0) +++ doc/example-scripts/rosetta-classes.tcl (revision 5693145107c55b5f64bf0fb487aa43e0f2238f1a) @@ -0,0 +1,26 @@ + +# == Rosetta Example: Classes +# For details see http://rosettacode.org/wiki/Classes +# +package req nx +package req nx::test + +nx::Class create summation { + :method init {} {set :v 0} + :public method add {x} {incr :v $x} + :public method value {} {return ${:v}} + :public method destroy {} {puts "ended with value [:value]"; next} +} + +# === Demonstrating the behavior in a shell: + +? {set sum [summation new]} "::nsf::__#0" +? {$sum value} 0 +? {$sum add 1} 1 +? {$sum add 2} 3 +? {$sum add 3} 6 +? {$sum add 4} 10 +? {$sum value} 10 + +# During the destroy of the object, +ended with value 10+ is printed +? {$sum destroy} "" Index: doc/example-scripts/rosetta-constraint-genericity.html =================================================================== diff -u -N --- doc/example-scripts/rosetta-constraint-genericity.html (revision 0) +++ doc/example-scripts/rosetta-constraint-genericity.html (revision 5693145107c55b5f64bf0fb487aa43e0f2238f1a) @@ -0,0 +1,834 @@ + + + + + +Listing of doc/example-scripts/rosetta-constraint-genericity.tcl + + + + + +
+
+

Rosetta Example: Constrained genericity

+
+ +
+
+
package req nx
+

Define the two classes Eatable and Fish. Eatable is a class +for all eatable things, a Fish is a subclass ant therefore +eatable.

+
+
+
nx::Class create Eatable
+nx::Class create Fish -superclass Eatable {
+  :property name
+}
+

A FoodBax may only contain eatable items. Therefore with we define +items as a property of type Eatable" which has a multiplicity of ++0..n (might contain 0 to n eatable items). Furthermore, we define +items as incremental, such we can add / remove items with item +add or item remove.

+
+
+
nx::Class create FoodBox {
+  :property item:object,type=::Eatable,0..n,incremental
+  :public method print {} {
+    set string "Foodbox contains:\n"
+    foreach i ${:item} {append string "   [$i name]\n"}
+    return $string
+  }
+}
+
+

Demonstrating the behavior in a shell:

+

Create two fishes, Wanda and Nemo:

+
+
+
% set f1 [Fish new -name "Wanda"]
+% set f2 [Fish new -name "Nemo"]
+

Create a Foodbox and add the two fishes:

+
+
+
% set fb [FoodBox new]
+% $fb item add $f1
+% $fb item add $f2
+

Return the print string of the contents:

+
+
+
% $fb print
+Foodbox contains:
+   Nemo
+   Wanda
+
+
+
+
+

+ + + Index: doc/example-scripts/rosetta-constraint-genericity.tcl =================================================================== diff -u -N --- doc/example-scripts/rosetta-constraint-genericity.tcl (revision 0) +++ doc/example-scripts/rosetta-constraint-genericity.tcl (revision 5693145107c55b5f64bf0fb487aa43e0f2238f1a) @@ -0,0 +1,49 @@ +# +# == Rosetta Example: Constrained genericity +# For details see http://rosettacode.org/wiki/Constrained_genericity +# +package req nx +package req nx::test + +# +# Define the two classes +Eatable+ and +Fish+. +Eatable+ is a class +# for all eatable things, a +Fish+ is a subclass ant therefore +# eatable. +# +nx::Class create Eatable +nx::Class create Fish -superclass Eatable { + :property name +} + +# +# A +FoodBax+ may only contain eatable items. Therefore with we define +# +items+ as a property of type +Eatable" which has a multiplicity of +# +0..n+ (might contain 0 to n eatable items). Furthermore, we define +# items as +incremental+, such we can add / remove items with +item +# add+ or +item remove+. +# +nx::Class create FoodBox { + :property item:object,type=::Eatable,0..n,incremental + :public method print {} { + set string "Foodbox contains:\n" + foreach i ${:item} {append string " [$i name]\n"} + return $string + } +} + +# === Demonstrating the behavior in a shell: +# Create two fishes, Wanda and Nemo: +? {set f1 [Fish new -name "Wanda"]} "::nsf::__#0" +? {set f2 [Fish new -name "Nemo"]} "::nsf::__#1" + +# Create a Foodbox and add the two fishes: +? {set fb [FoodBox new]} "::nsf::__#2" +? {$fb item add $f1} "::nsf::__#0" +? {$fb item add $f2} "::nsf::__#1 ::nsf::__#0" + +# Return the print string of the contents: +? {$fb print} {Foodbox contains: + Nemo + Wanda +} + Index: doc/example-scripts/rosetta-delegates.html =================================================================== diff -u -N --- doc/example-scripts/rosetta-delegates.html (revision 0) +++ doc/example-scripts/rosetta-delegates.html (revision 5693145107c55b5f64bf0fb487aa43e0f2238f1a) @@ -0,0 +1,808 @@ + + + + + +Listing of doc/example-scripts/rosetta-delegates.tcl + + + + + +
+
+

Rosetta Example: Delegates

+
+ +
+
+
package req nx
+
+nx::Class create Delegator {
+
+  # The class Delegator has a property named "delegatee" which is an
+  # object:
+
+  :property delegatee:object
+
+  # The method "operation" decides, whether it deletates the action to
+  # another object, or it performs the action itself.
+
+  :public method operation {} {
+    if {[info exists :delegatee]} {
+      ${:delegatee} operation
+    } else {
+      return "default implementatiton"
+    }
+  }
+}
+
+nx::Class create Delegatee {
+
+  # The class "Delgatee" might receice invocations from the class
+  # "Delegator"
+
+  :public method operation {} {
+    return "delegatee implementatiton"
+  }
+}
+
+

Demonstrating the behavior in a shell:

+

Create a Delegator, which has no delegatee defined. Therefore +delegator performs the action by itself, the default implementation.

+
+
+
% set a [Delegator new]
+% $a operation
+default implementatiton
+

Now, we set the delegatee; therefore, the delegatee will perform +the action.

+
+
+
% $a delegatee [Delegatee new]
+% $a operation
+delegatee implementatiton
+
+
+
+
+

+ + + Index: doc/example-scripts/rosetta-delegates.tcl =================================================================== diff -u -N --- doc/example-scripts/rosetta-delegates.tcl (revision 0) +++ doc/example-scripts/rosetta-delegates.tcl (revision 5693145107c55b5f64bf0fb487aa43e0f2238f1a) @@ -0,0 +1,50 @@ +# +# == Rosetta Example: Delegates +# For details see http://rosettacode.org/wiki/Delegates +# +package req nx +package req nx::test + +nx::Class create Delegator { + + # The class Delegator has a property named "delegatee" which is an + # object: + + :property delegatee:object + + # The method "operation" decides, whether it deletates the action to + # another object, or it performs the action itself. + + :public method operation {} { + if {[info exists :delegatee]} { + ${:delegatee} operation + } else { + return "default implementatiton" + } + } +} + +nx::Class create Delegatee { + + # The class "Delgatee" might receice invocations from the class + # "Delegator" + + :public method operation {} { + return "delegatee implementatiton" + } +} + +# === Demonstrating the behavior in a shell: +# +# Create a +Delegator+, which has no +delegatee+ defined. Therefore +# delegator performs the action by itself, the default implementation. +# +? {set a [Delegator new]} "::nsf::__#0" +? {$a operation} "default implementatiton" + +# +# Now, we set the +delegatee+; therefore, the delegatee will perform +# the action. +# +? {$a delegatee [Delegatee new]} "::nsf::__#1" +? {$a operation} "delegatee implementatiton" \ No newline at end of file Index: doc/example-scripts/rosetta-distinct-objects.html =================================================================== diff -u -N --- doc/example-scripts/rosetta-distinct-objects.html (revision 0) +++ doc/example-scripts/rosetta-distinct-objects.html (revision 5693145107c55b5f64bf0fb487aa43e0f2238f1a) @@ -0,0 +1,774 @@ + + + + + +Listing of doc/example-scripts/rosetta-distinct-objects.tcl + + + + + +
+
+

Rosetta Example: Multiple distinct objects

+
+ +
+
+
package req nx
+

Set the number of objects that should be created

+
+
+
% set n 100
+100
+

Create a sequence as a list with n instances of the class nx::Object

+
+
+
% set sequence {}
+% for {set i 0} {$i < $n} {incr i} {
+    lappend sequence [nx::Object new]
+}
+
+
+
+

+ + + Index: doc/example-scripts/rosetta-distinct-objects.tcl =================================================================== diff -u -N --- doc/example-scripts/rosetta-distinct-objects.tcl (revision 0) +++ doc/example-scripts/rosetta-distinct-objects.tcl (revision 5693145107c55b5f64bf0fb487aa43e0f2238f1a) @@ -0,0 +1,17 @@ +# == Rosetta Example: Multiple distinct objects +# For details see http://rosettacode.org/wiki/Multiple_distinct_objects +# +package req nx +package req nx::test + +# Set the number of objects that should be created +? {set n 100} 100 + +# Create a sequence as a list with +n+ instances of the class +nx::Object+ +? {set sequence {}} "" +? {for {set i 0} {$i < $n} {incr i} { + lappend sequence [nx::Object new] +} +} "" + + Index: doc/example-scripts/rosetta-polymorphic-copy.html =================================================================== diff -u -N --- doc/example-scripts/rosetta-polymorphic-copy.html (revision 0) +++ doc/example-scripts/rosetta-polymorphic-copy.html (revision 5693145107c55b5f64bf0fb487aa43e0f2238f1a) @@ -0,0 +1,778 @@ + + + + + +Listing of doc/example-scripts/rosetta-polymorphic-copy.tcl + + + + + +
+
+

Rosetta Example: Polymorphic copy

+
+ +
+
+
package req nx
+
+nx::Class create T {
+  :public method name {} {return T}
+}
+nx::Class create S -superclass T {
+  :public method name {} {return S}
+}
+
+

Demonstrating the behavior in a shell:

+

o1 and o2 are instances of T and S. $o1 name returns the same value as its copy, same for $o2

+
+
+
% set o1 [T new]
+% set o2 [S new]
+
+% $o1 name
+T
+% $o2 name
+S
+
+% [$o1 copy] name
+T
+% [$o2 copy] name
+S
+
+
+
+
+

+ + + Index: doc/example-scripts/rosetta-polymorphic-copy.tcl =================================================================== diff -u -N --- doc/example-scripts/rosetta-polymorphic-copy.tcl (revision 0) +++ doc/example-scripts/rosetta-polymorphic-copy.tcl (revision 5693145107c55b5f64bf0fb487aa43e0f2238f1a) @@ -0,0 +1,26 @@ +# +# == Rosetta Example: Polymorphic copy +# For details see http://rosettacode.org/wiki/Polymorphic_copy +# +package req nx +package req nx::test + +nx::Class create T { + :public method name {} {return T} +} +nx::Class create S -superclass T { + :public method name {} {return S} +} + +# === Demonstrating the behavior in a shell: +# +# +o1+ and +o2+ are instances of +T+ and +S+. +$o1 name+ returns the same value as its copy, same for +$o2+ + +? {set o1 [T new]} "::nsf::__#0" +? {set o2 [S new]} "::nsf::__#1" + +? {$o1 name} "T" +? {$o2 name} "S" + +? {[$o1 copy] name} "T" +? {[$o2 copy] name} "S" \ No newline at end of file Index: doc/example-scripts/rosetta-polymorphism.html =================================================================== diff -u -N --- doc/example-scripts/rosetta-polymorphism.html (revision 0) +++ doc/example-scripts/rosetta-polymorphism.html (revision 5693145107c55b5f64bf0fb487aa43e0f2238f1a) @@ -0,0 +1,840 @@ + + + + + +Listing of doc/example-scripts/rosetta-polymorphism.tcl + + + + + +
+
+

Rosetta Example: Polymorphism

+
+ +
+
+
package req nx
+
+nx::Class create Point {
+
+  :property x:double
+  :property y:double
+
+  :public method print {} {
+    return "Point(${:x},${:y})"
+  }
+}
+
+nx::Class create Circle -superclass Point {
+
+  :property radius:double
+
+  :public method print {} {
+    return "Circle(${:x},${:y},${:radius})"
+  }
+}
+
+

Demonstrating the behavior in a shell:

+

Create a point:

+
+
+
% set p [Point new -x 1.0 -y 2.0]
+% $p print
+Point(1.0,2.0)
+% $p x
+1.0
+

Create a circle:

+
+
+
% set c [Circle new -x 3.0 -y 4.0 -radius 5.0]
+

Copy the circle

+
+
+
% set d [$c copy]
+

Change the radius of the copied circle:

+
+
+
% $d radius 1.5
+1.5
+

Print the two circles:

+
+
+
% $c print
+Circle(3.0,4.0,5.0)
+
+% $d print
+Circle(3.0,4.0,1.5)
+
+
+
+
+

+ + + Index: doc/example-scripts/rosetta-polymorphism.tcl =================================================================== diff -u -N --- doc/example-scripts/rosetta-polymorphism.tcl (revision 0) +++ doc/example-scripts/rosetta-polymorphism.tcl (revision 5693145107c55b5f64bf0fb487aa43e0f2238f1a) @@ -0,0 +1,45 @@ + +# == Rosetta Example: Polymorphism +# For details see http://rosettacode.org/wiki/Polymorphism +# +package req nx +package req nx::test + +nx::Class create Point { + + :property x:double + :property y:double + + :public method print {} { + return "Point(${:x},${:y})" + } +} + +nx::Class create Circle -superclass Point { + + :property radius:double + + :public method print {} { + return "Circle(${:x},${:y},${:radius})" + } +} + +# === Demonstrating the behavior in a shell: + +# Create a point: +? {set p [Point new -x 1.0 -y 2.0]} "::nsf::__#0" +? {$p print} "Point(1.0,2.0)" +? {$p x} "1.0" + +# Create a circle: +? {set c [Circle new -x 3.0 -y 4.0 -radius 5.0]} "::nsf::__#1" +# Copy the circle +? {set d [$c copy]} "::nsf::__#3" + +# Change the radius of the copied circle: +? {$d radius 1.5} 1.5 + +# Print the two circles: +? {$c print} "Circle(3.0,4.0,5.0)" + +? {$d print} "Circle(3.0,4.0,1.5)" Index: doc/example-scripts/rosetta-serialization.html =================================================================== diff -u -N --- doc/example-scripts/rosetta-serialization.html (revision 0) +++ doc/example-scripts/rosetta-serialization.html (revision 5693145107c55b5f64bf0fb487aa43e0f2238f1a) @@ -0,0 +1,861 @@ + + + + + +Listing of doc/example-scripts/rosetta-serialization.tcl + + + + + +
+
+

Rosetta Example: Object serialization

+
+ +
+
+
package req nx
+package req nx::serializer
+
+nx::Class create Being {
+  :property {alive:boolean true}
+}
+
+nx::Class create Animal -superclass Being {
+  :property name
+  :public method print {} {
+    puts "i am ${:name} alive ${:alive}"
+  }
+}
+
+

Demonstrating the behavior in a shell:

+

Create a few animals

+
+
+
% Animal new -name "Fido"
+% Animal new -name "Lupo"
+% Animal new -name "Kiki" -alive false
+

Print the created animals

+
+
+
% foreach i [Animal info instances] { $i print }
+

The loop prints:
+ i am Kiki alive false
+ i am Lupo alive true
+ i am Fido alive true

+

Serialize the animals to a file

+
+
+
% set f [open /tmp/dump w]
+file5
+% foreach i [Animal info instances] { puts $f [$i serialize] }
+% close $f
+

Destroy all animal instances:

+
+
+
% foreach i [Animal info instances] { $i destroy }
+% puts ===========
+

Print the existing animals (will print nothing)

+
+
+
% foreach i [Animal info instances] { $i print }
+% puts ===========
+

Load the animals again …

+
+
+
% source /tmp/dump
+

and print it. The print output is the same as above

+
+
+
% foreach i [Animal info instances] { $i print }
+
+
+
+
+

+ + + Index: doc/example-scripts/rosetta-serialization.tcl =================================================================== diff -u -N --- doc/example-scripts/rosetta-serialization.tcl (revision 0) +++ doc/example-scripts/rosetta-serialization.tcl (revision 5693145107c55b5f64bf0fb487aa43e0f2238f1a) @@ -0,0 +1,51 @@ + +# == Rosetta Example: Object serialization +# For details see http://rosettacode.org/wiki/Object_serialization +# +package req nx +package req nx::test +package req nx::serializer + +nx::Class create Being { + :property {alive:boolean true} +} + +nx::Class create Animal -superclass Being { + :property name + :public method print {} { + puts "i am ${:name} alive ${:alive}" + } +} + +# === Demonstrating the behavior in a shell: +# Create a few animals +? {Animal new -name "Fido"} "::nsf::__#0" +? {Animal new -name "Lupo"} "::nsf::__#1" +? {Animal new -name "Kiki" -alive false} "::nsf::__#2" + +# Print the created animals +? {foreach i [Animal info instances] { $i print }} "" + +# The loop prints: + +# +i am Kiki alive false+ + +# +i am Lupo alive true+ + +# +i am Fido alive true+ +# +# Serialize the animals to a file +? {set f [open /tmp/dump w]} "file5" +? {foreach i [Animal info instances] { puts $f [$i serialize] }} "" +? {close $f} "" + +# Destroy all animal instances: +? {foreach i [Animal info instances] { $i destroy }} "" +? {puts ===========} "" + +# Print the existing animals (will print nothing) +? {foreach i [Animal info instances] { $i print }} "" +? {puts ===========} "" + +# Load the animals again ... +? {source /tmp/dump} "" + +# and print it. The print output is the same as above +? {foreach i [Animal info instances] { $i print }} "" Index: doc/example-scripts/rosetta-singleton.html =================================================================== diff -u -N --- doc/example-scripts/rosetta-singleton.html (revision 0) +++ doc/example-scripts/rosetta-singleton.html (revision 5693145107c55b5f64bf0fb487aa43e0f2238f1a) @@ -0,0 +1,837 @@ + + + + + +Listing of doc/example-scripts/rosetta-singleton.tcl + + + + + +
+
+

Rosetta Example: Singleton

+
+ +
+

A Singleton Class

+
+
+
package req nx
+
+nx::Class create Singleton {
+  #
+  # We overload the system method "create". In the modified method we
+  # save the created instance in the instance variable named
+  # "instance"
+  #
+  :variable instance:object
+
+  :public class method create {args} {
+    return [expr {[info exists :instance] ? ${:instance} : [set :instance [next]]}]
+  }
+}
+
+
+

Demonstrating the behavior in a shell:

+

Calling Singleton new multiple times returns always the same object:

+
+
+
% expr {[Singleton new] eq [Singleton new]}
+1
+
+
+

A Singleton Meta-class

+

Alternatively, we can follow a more generic approach and define a +metaclass which allows to define several application classes as +singletons. The metaclass has the most general metaclass nx::Class +as superclass. In contrary to the example obove, the create method +is not defined as a class method, but it will be inherited to its +instances (to the application classes).

+
+
+
nx::Class create Singleton -superclass nx::Class {
+  #
+  # We overload the system method "create". In the modified method we
+  # save the created instance in the instance variable named
+  # "instance"
+  #
+  :variable instance:object
+
+  :public method create {args} {
+    return [expr {[info exists :instance] ? ${:instance} : [set :instance [next]]}]
+  }
+}
+

Create an application class named Counter as a singleton:

+
+
+
% Singleton create Counter
+::Counter
+

Calling Counter new multiple times returns always the same object:

+
+
+
% expr {[Counter new] eq [Counter new]}
+1
+
+
+
+
+

+ + + Index: doc/example-scripts/rosetta-singleton.tcl =================================================================== diff -u -N --- doc/example-scripts/rosetta-singleton.tcl (revision 0) +++ doc/example-scripts/rosetta-singleton.tcl (revision 5693145107c55b5f64bf0fb487aa43e0f2238f1a) @@ -0,0 +1,55 @@ +# +# == Rosetta Example: Singleton +# For details see http://rosettacode.org/wiki/Singleton +# +# === A Singleton Class +package req nx +package req nx::test + +nx::Class create Singleton { + # + # We overload the system method "create". In the modified method we + # save the created instance in the instance variable named + # "instance" + # + :variable instance:object + + :public class method create {args} { + return [expr {[info exists :instance] ? ${:instance} : [set :instance [next]]}] + } +} + +# === Demonstrating the behavior in a shell: +# +# Calling +Singleton new+ multiple times returns always the same object: +? {expr {[Singleton new] eq [Singleton new]}} 1 + +# +# === A Singleton Meta-class +# +# Alternatively, we can follow a more generic approach and define a +# metaclass which allows to define several application classes as +# singletons. The metaclass has the most general metaclass +nx::Class+ +# as superclass. In contrary to the example obove, the +create+ method +# is not defined as a class method, but it will be inherited to its +# instances (to the application classes). +# +nx::Class create Singleton -superclass nx::Class { + # + # We overload the system method "create". In the modified method we + # save the created instance in the instance variable named + # "instance" + # + :variable instance:object + + :public method create {args} { + return [expr {[info exists :instance] ? ${:instance} : [set :instance [next]]}] + } +} + +# Create an application class named +Counter+ as a singleton: + +? {Singleton create Counter} ::Counter + +# Calling +Counter new+ multiple times returns always the same object: +? {expr {[Counter new] eq [Counter new]}} 1 \ No newline at end of file