Jump to: main text

Array examples from Inline::SLang

The following code and examples can be found in the Inline::SLang distribution available from CPAN. The output was created using version 1.00 of the module, using the PDL support, together with version 1.4.9 of the S-Lang library.

Since the support for arrays in S-Lang and Perl do not match, the conversion of array values between the two languages is not entirely seemless, as shown in the examples below. The datatypes example page may also be useful. The support for arrays is described in the Inline::SLang::Array documentation that comes with the module.

Array references can be - and indeed are - used, but there is a potential loss of information (about the data type and size of the array, not with the array contents) in the conversion and the conversion is not very efficient. Piddles - the fundamental data object of the Perl Data Language - are a much better choice, since the conversion is much quicker and you do not lose information about data type and array size; however, this is only good for numeric types and if you have PDL installed. The third option is to use a Perl Array_Type object to store the data; the Array_Type class is part of Inline::SLang and is as inefficient as using an array reference but does retain knowledge about the array size and type.

The short version of the previous paragraph is that you should use piddles for numeric arrays and array references for the rest. The Array_Type object is probably going to be rarely used.

A simple example

use Inline 'SLang';

# you can send arrays to S-Lang
print_in_slang( [ 1, 2, 4 ] );

# and get them back from S-Lang
$aref = get_from_slang();
print "The array contains: " . join(',', @$aref) . "\n";

__END__
__SLang__

define print_in_slang (arr) {
  variable adims, ndim, atype;
  ( adims, ndim, atype ) = array_info(arr);
  vmessage( "Array has type=%S with %d dims", atype, ndim );
  foreach ( arr ) {
    variable val = ();
    vmessage( "  Value = %s", string(val) );
  }
}
define get_from_slang() { return ["a string","another one","3"]; }

which, when run, produces

Array has type=Integer_Type with 1 dims
  Value = 1
  Value = 2
  Value = 4
The array contains: a string,another one,3

Using sl_array

use Inline 'SLang' => Config => EXPORT =>
     [ 'sl_array', 'Integer_Type' ];
use Inline 'SLang';

my $aref = [ 1, 3, 2 ];
foo( $aref );
foo( sl_array( $aref, "Int_Type" ) );
foo( sl_array( $aref, [3] ) );
foo( sl_array( $aref, [3], Integer_Type() ) );

__END__
__SLang__

define foo(x) { vmessage("Array has type: %S", _typeof(x) ); }

which, when run, produces

Array has type: Integer_Type
Array has type: Integer_Type
Array has type: Integer_Type
Array has type: Integer_Type

Array information

In this example we use a variety of methods to find out information about the array, such as its type and dimensionality.

use strict;

use Inline 'SLang' => Config => EXPORT => [ 'sl_array2perl' ];
use Inline 'SLang';

# use array references for all S-Lang arrays
sl_array2perl(0);
my $a0 = get_array();
print "Array returned as an " . ref($a0) . "\n";
print "  dim size = " . (1+$#$a0) . "\n";

# use Array_Type for all S-Lang arrays
sl_array2perl(1);
my $a1 = get_array();
print "Array returned as an " . ref($a1) . "\n";
my ( $dims, $ndim, $atype ) = $a1->array_info();
print "  dim size = $$dims[0]\n";
print "  type     = $atype\n";

# use a piddle (assumes Inline::SLang::sl_have_pdl() == 1)
sl_array2perl(2);
my $a2 = get_array();
print "Array returned as an " . ref($a2) . "\n";
print "  dim size = " . $a2->getdim(0) . "\n";
print "  type     = " . $a2->type . "\n";

__END__
__SLang__

define get_array() { return [ 14.0, 3 ]; }

which, when run, produces

Array returned as an ARRAY
  dim size = 2
Array returned as an Array_Type
  dim size = 2
  type     = Double_Type
Array returned as an PDL
  dim size = 2
  type     = double

Using array references to represent arrays in Perl

In most cases the conversion between S-Lang and Perl arrays should be obvious, as this example hopes to demonstrate. The next example uses piddles rather than array references.

use strict;
use Inline 'SLang';
use Data::Dumper;

# ensure that we convert S-Lang arrays to array references
Inline::SLang::sl_array2perl(0);

my $a1 = send_and_get( [ "hi", "there", "", "a string" ] );
print "\nPerl sent:\n", Dumper($a1), "\n";

__END__
__SLang__

define send_and_get (in) {
  if ( typeof(in) != Array_Type ) error( "Error!" );
  variable adims, ndims, atype;
  ( adims, ndims, atype ) = array_info(in);
  vmessage( "S-Lang sent a %d dim array of %S variables", ndims, atype );
  variable elem;
  foreach ( in ) {
    elem = ();
    vmessage( "  element = '%S'", elem );
  }

  % create the output array
  variable out = [2:7];
  reshape( out, [2,3] );
  return out;
}

The output of this code is:

S-Lang sent a 1 dim array of String_Type variables
  element = 'hi'
  element = 'there'
  element = ''
  element = 'a string'

Perl sent:
$VAR1 = [
          [
            2,
            3,
            4
          ],
          [
            5,
            6,
            7
          ]
        ];

Using piddles to represent numeric arrays in Perl

In the previous example we made sure that S-Lang arrays were converted to array references; here we use piddles (for numeric arrays).

use strict;
use Inline 'SLang';
use PDL;

# ensure that we convert numeric S-Lang arrays to piddles
Inline::SLang::sl_array2perl(2);

# NOTE:
#   in S-Lang we have a [2,3] array but
#      in PDL this is a [3,2] array!
#
my $a1 = send_and_get( sequence(5)/2.0 );
print "\nPerl sent:\n", $a1->info, "\n";
print $a1, "\n";

__END__
__SLang__

define send_and_get (in) {
  if ( typeof(in) != Array_Type ) error( "Error!" );
  variable adims, ndims, atype;
  ( adims, ndims, atype ) = array_info(in);
  vmessage( "S-Lang sent a %d dim array of %S variables", ndims, atype );
  variable elem;
  foreach ( in ) {
    elem = ();
    vmessage( "  element = '%S'", elem );
  }

  % create the output array
  variable out = [2:7];
  reshape( out, [2,3] );
  return out;
}

The output of this code is:

S-Lang sent a 1 dim array of Double_Type variables
  element = '0'
  element = '0.5'
  element = '1'
  element = '1.5'
  element = '2'

Perl sent:
PDL: Long D [3,2]

[
 [2 3 4]
 [5 6 7]
]

Note: as indicated in the example code, the array dimensions are reversed when converting between S-Lang arrays and piddles (it is only relevant for arrays with more than one dimension). This is because S-Lang uses the C-style of indexing arrays - the last index loops fastest - whilst PDL uses the FORTRAN-style of indexing, where the first index loops fastest.