ePolyglot: Examination and development of multilanguage programming using Eiffel, Python, and Haskell | ||
---|---|---|
Prev | Chapter 7. Shadow Classes | Next |
So how well do our new Python primitive classes hold up, and how easily can they be used? The following sample program uses the new hierarchy for a simple demonstration of many of the PYTHON_OBJECT classes:
Example 7-1. The "primitives_test.e" sample program
class PRIMITIVES_TEST inherit PYTHON_CLIENT creation make feature do_string_demo is --demonstrate use of python string primitives local s : PYTHON_STRING do std_output.put_string( "Python strings can be created from % %Eiffel strings, and vice versa.%N" ) std_output.put_string( "Creating Python string 'Hello, World!'%N" ) create s.from_string( "Hello, World!" ) std_output.put_string( "Created string: " + s.to_string + "%N%N") end do_number_demo is --demonstrate use of python number primitives local a, b, c : PYTHON_INTEGER af, bf : PYTHON_FLOAT do std_output.put_string( "Python numbers can be created from % %Eiffel numbers, and%Ncan be % %manipulated in the same ways:%N" ) create a.from_integer( 5 ) create b.from_integer( 6 ) create c.from_integer( 10 ) std_output.put_string( "5+6+10 = " ) std_output.put_integer( (a + b + c).to_integer ) std_output.put_new_line std_output.put_string( "10 / 5 = " ) std_output.put_integer( ( c / a ).to_integer ) std_output.put_new_line std_output.put_string( "10 / 6 = " ) std_output.put_integer( ( c / b ).to_integer ) std_output.put_new_line std_output.put_string( "Remainder of 10 / 6 : " ) std_output.put_integer( (c \\ b).to_integer ) std_output.put_new_line --similar acts with floating point create af.from_double( 2.5 ) create bf.from_double( 6.353 ) std_output.put_string( "2.5 + 6.353 = " ) std_output.put_double( ( af + bf ).to_double ) std_output.put_new_line std_output.put_string( "6.353 / 2.5 = " ) std_output.put_double( ( bf / af ).to_double ) std_output.put_new_line std_output.put_new_line end do_list_demo is --demonstrate use of Python lists local a : PYTHON_LIST do create a.make std_output.put_string( "Python lists can be created easily, % %and support many of the same% %%Nfeatures as Eiffel arrays...but not all.%N" ) std_output.put_string( "Creating a list of strings 'Hello', 'Eiffel'% % 'world!'%N" ) a.append( python_object_factory.new_python_string( "Hello" ) ) a.append( python_object_factory.new_python_string( "Eiffel" ) ) a.append( python_object_factory.new_python_string( "World!" ) ) std_output.put_string( "Python representation: " + a.to_string + "%N" ) std_output.put_string( "Replacing element 1:%N" ) a.put( python_object_factory.new_python_string( "Python" ), 1 ) std_output.put_string( "Python representation: " + a.to_string + "%N" ) std_output.put_string( "Inserting 'or Eiffel' after 'Python':%N" ) a.insert( python_object_factory.new_python_string( "or" ), 2 ) a.insert( python_object_factory.new_python_string( "Eiffel" ), 3 ) std_output.put_string( "Python representation: " + a.to_string + "%N" ) std_output.put_string( "Taking or setting slices is also possible.%N%N" ) end do_dictionary_demo is --demonstrate use of Python dictionaries local a : PYTHON_DICTIONARY do create a.make std_output.put_string( "Python dictionaries can be used to % %implement mappings.%N" ) std_output.put_string( "creating the simple dictionary { 'a': 'Hello',% % 'b' : 'World!' }%N" ) a.set_item_string( "b", python_object_factory.new_python_string( "World!" ) ) a.set_item_string( "a", python_object_factory.new_python_string( "Hello" ) ) std_output.put_string( "Python representation: " + a.to_string + "%N" ) std_output.put_string( "Keys: " + a.keys.to_string + "%N" ) std_output.put_string( "Values: " + a.values.to_string + "%N" ) std_output.put_string( "Value of a: " + a.get_item_string( "a" ).to_string + "%N") end make is do py_initialize do_string_demo do_number_demo do_list_demo do_dictionary_demo rescue if not py_err_occurred.is_null then py_err_print end end end |
While voluminous, it is designed to showcase many of the features of the PYTHON_OBJECT hierarchy: object creation and use, manipulation of objects from within Eiffel, and general ease of use. Unfortunately, any time you mix other languages or libraries with Eiffel, you lose some of the simplicity of the creation process, and so the details of making this simple example are a bit confusing, involving rules for SWIG and the addition of some C code to the program's compilation line. For more details of the make process, examine the files production/examples/examples_common/boilerplate.mk.in and production/examples/primitives/Makefile.in. While the Makefile is only slightly complex, the above source file was the only actual code written to take advantage of the embedded Python interpreter. When run, it produces the following output:
Example 7-2. Output from the "primitives_test.e" sample program
Python strings can be created from Eiffel strings, and vice versa. Creating Python string 'Hello, World!' Created string: Hello, World! Python numbers can be created from Eiffel numbers, and can be manipulated in the same ways: 5+6+10 = 21 10 / 5 = 2 10 / 6 = 1 Remainder of 10 / 6 : 4 2.5 + 6.353 = 8.853000 6.353 / 2.5 = 2.541200 Python lists can be created easily, and support many of the same features as Eiffel arrays...but not all. Creating a list of strings 'Hello', 'Eiffel' 'world!' Python representation: ['Hello', 'Eiffel', 'World!'] Replacing element 1: Python representation: ['Hello', 'Python', 'World!'] Inserting 'or Eiffel' after 'Python': Python representation: ['Hello', 'Python', 'or', 'Eiffel', 'World!'] Taking or setting slices is also possible. Python dictionaries can be used to implement mappings. creating the simple dictionary { 'a': 'Hello', 'b' : 'World!' } Python representation: {'b': 'World!', 'a': 'Hello'} Keys: ['b', 'a'] Values: ['World!', 'Hello'] Value of a: 'Hello' |