| ePolyglot: Examination and development of multilanguage programming using Eiffel, Python, and Haskell | ||
|---|---|---|
| Prev | Chapter 14. All three: Eiffel, Python, and Haskell together | Next |
The tri-language program required few changes from its bi-lingual counterpart in the previous chapter. In fact, none of the Haskell interface files were changed, so they are not duplicated here. The only changes were a routine to shuffle values from Python lists into Eiffel arrays of doubles, and of course the Python script to load the values from disk. Values were provided in the following format:
Example 14-1. Data file for regression_test
130,186 650, 699 99, 132 150, 272 128, 291 302, 331 95, 199 945, 1890 368, 788 961, 1601 |
These values were loaded and parsed by the Python function paired_arrays_from_file, located in the loader.py module:
Example 14-2. The loader.py module
#simple module to load numbers from a file
import re
def paired_arrays_from_file( filename ) :
a_series = []
b_series = []
f = open(filename, "r" )
lines = f.readlines()
regex = re.compile( r"^\s*(\S*?),\s*(\S*?)\s*$" )
for line in lines :
matches = regex.match( line )
if len( matches.group( 1 ) ) > 0 and len( matches.group( 2 ) ) > 0 :
a_series.append( float( matches.group( 1 ) ) )
b_series.append( float( matches.group( 2 ) ) )
return( a_series, b_series ); |
The loader.py module and Haskell code were controlled by the overall application regression_test.e:
Example 14-3. The regression_test.e source file
class REGRESSION_TEST
inherit
REGRESSION_WRAPPER
PYTHON_CLIENT
creation
make
feature
array_from_python_list( pyobj : PYTHON_OBJECT ) : ARRAY[ DOUBLE ] is
local
i : INTEGER
n : PYTHON_FLOAT
pyarr : PYTHON_LIST
do
create pyarr.make_from_python_object( pyobj )
create Result.with_capacity( pyarr.length, 0 )
from i := pyarr.lower until i > pyarr.upper loop
create n.make_from_python_object( pyarr.item( i ) )
Result.add_last( n.to_double )
i := i + 1
end
end
show_regression( filename : STRING ) is
local
series_a, series_b : ARRAY[ DOUBLE ]
m : LOADER
t : PYTHON_TUPLE
r : INTEGER
do
py_initialize
r := py_run_simple_string( "import sys" );
r := py_run_simple_string( "sys.path.append( '.' )" )
start_haskell
create m.make
create t.make_from_python_object( m.paired_arrays_from_file( << filename >> ) )
series_a := array_from_python_list( t.item( 0 ) )
series_b := array_from_python_list( t.item( 1 ) )
io.put_string( "%N%NLinear regression of series: Beta-0: " )
io.put_double( beta_0( series_a, series_a.count, series_b, series_b.count ) )
io.put_string( " Beta-1: " )
io.put_double( beta_1( series_a, series_a.count, series_b, series_b.count ) )
io.put_new_line
end
make is
do
if argument_count /= 1 then
io.put_string( "Usage : regression_test filename%N%N" )
else
show_regression( argument( 1 ) )
end
rescue
if not py_err_occurred.is_null then
py_err_print
end
end
end
|
The resultant output is the same as the earlier example program, which indicates that we have done our job correctly:
Example 14-4. Output from the poly_regression version of regression_test
[vputz@yak_prime poly_regression]$ ./regression_test test_1 Linear regression of series: Beta-0: -22.552533 Beta-1: 1.727932 |
At last, we have realized the vision of multilingual programming using Eiffel, Haskell, and Python together in the same executable.