Nombas > SE:ISDK DevSpace > Tips > Python Equivalents

 

Language Migration from Python
EcmaScript Equivalents for those migrating from Python

This document is an introduction to the JavaScript language (aka EcmaScript AKA ScriptEase) for those who are already familiar with the Python scripting language.

Python and JavaScript are very similar languages: they both closely follow most of the syntax and control flow of the 'C' programming language, they both extend that syntax into an object-oriented and extensible script language, and they both are designed to be embedded within C/C++/Java applications as an extension or command language for that application. In most cases the differences are only in terminology.

Because the languages are so similar, this document will be brief. It will cover only those areas where a Python script writer may have difficulty finding the equivalent capability in JavaScript. (If you are a Python user, moving to JavaScript, and have issues that you think should be added to this document then please visit http://support.nombas.com/ Please do not send Dr. Scripter flames about "why my embedded script language is so much better than yours!!!"--the Doctor is only interested in helping, and is not interested in entering into holy language wars)

   ---------- Revision History for this document --------------
   Mar 11 2003 - Initial document
   ------------------------------------------------------------

Topics


dictionaries

A Python "dictionary" is an unordered set of key:value pairs. The equivalent concept in JavaScript is the "associative array" or, more simply, the Object. The syntax for using a Python dictionary is part of the standard behavior for a JavaScript Object (and all objects which inherit from Object, i.e. all objects).

 Python code:

   emp = { 'name':'john',  'sal':50000 }
   emp['food'] = 'pie'

 JavaScript equivalent code:

   emp = { 'name':'john',  'sal':50000 }
   emp['food'] = 'pie'
      or
   emp = { name:'john', sal:50000 }
   emp.food = 'pie'  // note that emp.food==emp['food']

other common Python dictionary syntax involves keys() to enumerate, del to delete, and has_key() to determine if a key exists, as demonstrated in this code

 Python code:

   emp = { 'name':'john', 'sal':50000, 'food':'pie' }
   del emp['sal']
   k = emp.keys()          # k = ['name', 'food' ]
   h = emp.has_key('sal')  # h = 0

 JavaScript equivalent code

   emp = { 'name':'john', 'sal':50000, 'food':'pie' }
   delete emp[sal]       // or delete emp.sal
   for ( m in emp )      // for(...in...) enumerates members
      k = m;             // k='name' then k='food'
   h = 'sal' in emp      // h = false

In Python a key can be any immutable data, which including tuples. Using a tuple as a key does not have a direct JavaScript equivalent, although it would be very close to use the toString() or toSource() method on the JavaScript Array (similar to tuple) to represent the member name (i.e. key).


lists

A Python list is equivalent to a JavaScript Array object. The syntax for initializing them can even be the same, e.g.:

 Python code:

   a = [ 'blue', 42, [1,2,3], 'dog' ]
   b = a[1]       # b = 42
   c = a[2][1]    # c = 2
   l = len(a)     # l = 4
   l = len(l[2])  # l = 3

 JavaScript equivalent code

   a = [ 'blue', 42, [1,2,3], 'dog' ]
   b = a[1]         # b = 42
   c = a[2][1]      # c = 2
   l = a.length     // l = 4
   l = l[2].length  // l = 3

Except for the difference in determining length (a Python len() function vs a JavaScript Array property), these scripts are identical, including nesting of lists within lists (Arrays within Arrays).

Python lists differ from JavaScript Arrays in that operations on lists (e.g. replace, remove, insert) are part of the Python language syntax (e.g., a[0:2]), whereas the same operations on Arrays are instance methods of the Array object (e.g. a.slice(), a.join(), etc...)). (This difference goes along with a standard design philosophy behind EcmaScript that instead of adding language syntax or more data types, it is preferable to extend the capabilities through defining new object types and methods, and inheriting from those.)

Functionally, the capabilities of Python lists and JavaScript Arrays are equivalent--the difference being that a slice of a list is part of the Python language syntax, but a slice of an array is a method of that array. (Note: with the ScriptEase capabilities of making all operators on objects dynamic, and operator overloading on those objects, it would be possible to implement the python-like a[1:2]=[blah] syntax, but that would probably be confusing to someone with a pure-javascript background who later came across the unfamiliar-looking script.)


tuples

A Python tuple is just like a Python list except that the elements of a tuple are immutable. Python tuples also differ from lists in that tuples are initialized with the parenthesis instead of square brackets. i.e.

 Python code:
   a = [ 'blue', 42, 'dog' ]  # a is a list
   b = ( 'blue', 42, 'dog' )  # b is a tuple

There is no inherent language feature of JavaScript that maps directly to a tuple. The most direct JavaScript equivalent of a tuple would be an Array where each member of that array has its DONTDELETE and READONLY attributes set. There could be many ways to accomplish the creation of a tuple with ScriptEase, most of which would involve creating an array and applying the DONTDELETE and READONLY attributes to each element (the other option would be to disable the put callback after the array has been created).

One interesting approach, done through the script language itself, would be to add a tuple() method to instances of the Array object, so that after an array was created it could then be turned into a tuple. Here's an example of what the script may look like:

   function Array.prototype.tuple()
   {
      // for each element in this, apply readonly and dontdelete
      for ( var i = 0; i < this.length; i++ )
         setAttributes(this[i],DONT_DELETE | READ_ONLY );
   }

The above approach could be applied in a javascript script such as this:

 JavaScript code
   a = [ 'blue', 42, 'dog' ]          // a is an Array
   b = [ 'blue', 42, 'dog' ].tuple()  // b is a tuple 

The approach I would prefer, if you really want the concept of a tuple in the language, would just be to create a tuple() function that would take all of its arguments and put them into an array while making each member dont_delete and disabling further put() functions so that no members can be added or changed. The C code for such a tuple() method, using the ScriptEase ISDK/C, would look like this:

 C code for implementing the tuple() functions

   // create callbacks so that no put can happen to a tuple
   sebool JSE_CFUNC FAR_CALL tuple_put(secontext se,sestring prop)
   {
      // do nothing; do not allow any puts to this object
      return True;
   }
   struct seObjectCallbacks tuple_callbacks =
   { NULL, tuple_put, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };

   // this C code is called from script calling tuple(parm1,parm2,parm3,...)
   SE_CALLBACK(void) tuple(secontext se, sememcount argc)
   {
      seobject ret;
      sememcount i;

      // create an array object
      ret = seMakeObject(se);
      seSetArray(se,ret,0);  // shortcut to calling the Array constructor

      // for each argument to this function, set dontdelete element of array object
      for ( i = 0; i < argc; i++ )
      {
         seAssign( se, ret,SE_NUM(i), SE_ARGS,SE_INDEX(i) );
         seSetAttribs( se, ret,SE_NUM(i), SE_READONLY|SE_DONTDELETE );
      }

      // set the do-nothing put function so no additions can be made
      seSetCallbacks(se, ret,SE_VALUE, &tuple_callbacks);

      // return our new object from this function
      sePutObject(se,SE_RETURN,SE_VALUE,ret);
   } 

With this tuple() method now added, the following JavaScript will show the difference between making a tuple and a plain Array.

 JavaScript code
   a = [ 'blue', 42, 'dog' ]          // a is an Array
   b = tuple( 'blue', 42, 'dog' )     // b is a tuple 

(Should we provide a better version of tuple? A complete tuple class or a better version of the above tuple wrapper function? Maybe we're missing some need. If you have ideas on this then please tell http://support.nombas.com/)


gotchas

In moving from Python to JavaScript, these are a few items to watch out for:

  • default global variables - According to the EcmaScript specification, a variable that is not labeled within a method with the var keyword is automatically assumed to be a global variable. This can often lead to problems when two methods both use the same variable name (such as if one method looping through i calls another method looping through its own i variable, with neither declaring var i.

    With the ScriptEase ISDK there are a couple of ways to ease around this problem. The first is to use the SE_OPT_DEFAULTLOCAL flag in the seContextParam seOptions field. SE_OPT_DEFAULTLOCAL reverses the EcmaScript standard so that variables not declared globally are assumed to be local variables. The other option is to use the SE_OPT_REQUIREVAR flag instead (although both flags may be used together). SE_OPT_REQUIREVAR tells the engine to create an error whenever it encounters a variable that has not been declared with the var keyword, and so if any variable is used without declaring it first an exception will be generated specifying the error, variable, script, and line number. We prefer the SE_OPT_REQUIREVAR flag because 1) the default-local-var option is non-standard and so may lead your users to be confused when reading standards-compliant scripts, and 2) the SE_OPT_REQUIREVAR flag has the added benefit of helping to catch typographical errors such as using a variable Count when it was declared as count.

If you have comments about this document, or what should be added to this document, write to http://support.nombas.com/.

Home | Scripting | Products | Purchase | Download | Support | Company

Copyright ©2001, Nombas, Inc. All Rights Reserved.
Questions? Visit
http://support.nombas.com/