Introduction

This article was written to provide a complete and comprehensive perspective on the programming language Euphoria, unlike most articles, which seem very ignorant towards most elegance of Euphoria.

Euphoria is a 32-bit programming language currently available for both the win32 and the dos32 platform. It doesn’t have many "bells and whistles", but has a very fanatic group of users. It has both a shareware version and a low-priced complete version. The only limitation of the shareware version is the 300-statement limit on extensive explanation when a run-time error occurs.

Unfortunately most people take a look at Euphoria, and put it in the category "scripting languages" or maybe once in a while somebody actually tries it and then considers it to be a good alternative to basic. However, most people do not give Euphoria a good chance to prove itself nor do they think about its elegance at all.

Placing Euphoria

Euphoria is a third generation language; you have to tell it how to solve a programming problem. Although some programming languages claim to be of the fourth generation, they are usually not.

Euphoria itself has only claimed to be a functional language. It does not claim to be object oriented but I have to disagree with that. It does not force you to program object-oriented nor does it have any specific syntax that would distinguish object-oriented code from procedural code. Yet, its scope rules and flexible data structures allow you to simulate any method of programming including object-oriented. Not because there are specific object-oriented statements, but because you can do a lot with a few statements in Euphoria. You could consider Euphoria to be more than object-oriented, because you have a lot of freedom of programming style. In my honest opinion, you have more freedom of programming style than you will have with any other language. That is indeed only because of the flexible and generic language definition. The only one to force a certain data structure is the programmer itself.

Euphoria is a bit more system-specific than, for example, Java. Although the documentation clearly points out which routines are system dependent. Unlike all the other routines, misuse of these routines can, of course, cause a crash, which will usually be caught by the built-in memory extender or generate a protection fault in windows.

Like Java, Euphoria is interpretive language, and does not need any compilation at all. It will therefore never crash, but always end your program with a clear message identifying what went wrong, why it went wrong and usually what you could do to fix it. However because of its interpretive nature, some errors are not caught before the code is executed, like a division by a zero valued constant, which some compilers do point out as an error during compilation. Unlike most interpreters, Euphoria is extremely fast, however this is due not only to its speed per statement, but also by the fewer statements you need to perform generic tasks.

At first sight, Euphoria looks like a scripting language, an alternative to basic or another lisp clone. Those first sights are right, but not complete. Euphoria can be used as a scripting language, because of its interpretive nature and because you can have statements on the upper level. The 92 statements are very close to real English and Euphoria syntax does not include any weird acronyms or symbols, although at some places, technical or more common expressions are used. There is no need to add to the complex jargon of programming, and they didn’t.

It is a lot faster than basic, has generic routines, nice debugging features and is easy to install. Therefore it is a great teaching language, and allows novice programmers to try out lots of stuff, without confusing them too much.

As for lisp, at some times Euphoria does appear to have stolen some of Lisp’s nifty tricks. Nevertheless, most lisp clones are put in a shame by Euphoria's performance. In addition, it even simplified some of Lisp’s childish and strange ways of handling things. Strings are handled, as a separate data type by Lisp, while Euphoria considers them to be sequences (a one-dimensional array) containing ASCII values, so there is no need for special string manipulation routines. You can use the standard manipulation methods you also use for any other sequence.

Structure of a program

Statements can be called, but always require the appropriate fixed number of arguments. Functions can be called, like statements, but have to assign or use the returned value. You are not allowed to discard the value, you have to at least assign it to something. You can use a dummy variable if you do wish to do so. This is so you, and anyone else seeing your code, will always be aware that you are discarding a value.

Variables can be local to a routine, local to a file, or global. When you define a variable to be local to a routine, its memory will be released at the end of a routine call. There is no way to declare a variable static to a routine, but those declared local to a file are always static and their memory is not released until the interpreter can determine that they are no longer in use. Variables always have to be declared and initialized before they can be used, unlike certain other languages, i.e. BASIC, they are not quietly set to zero, you will always be able to see which variable a certain routine, or file is using.

Routines can be declared local to a file or global. You can call a routine recursively, but for mutual-recursion, routine pointers are to be used. There are also a few built-in routines, but routines for graphics, mouse, sorting, and pattern matching are provided as include files. An ‘include’ file is just a normal Euphoria program, but all globally defined routines are exportable. If it contains top-level statements, they will be executed at the point where the file is included.

A top-level statement can include other files, but not inside any statement block. There is thus no way to choose the file you wish to include at run-time.

You can also declare a variable as a constant. The value can be calculated in real-time, but once the constant is declared the value is locked-in. You are not allowed to tell Euphoria of what type a certain constant is. The data type will be determined when you lock-in the value. Constants can only be declared local to a file or global. Because they can not be declared inside of routines, the interpreter still has the opportunity to put the values strait into your code, and thereby eliminating all overhead.

Variables and data types

Euphoria only knows two data types: the sequence, and the atom. An atom is numeric value that will automatically use more memory when its value no longer fits in the reserved memory. A sequence is a list of objects. If you don't want your value to be converted to a floating-point value, because you can’t afford to loose any precision, you can limit this for a variable by declaring it as ‘integer’. However, an integer in Euphoria can only contain 31-bit integer values. In addition, if you want, for example, a routine to be able to work with both sequences and atoms, you can declare the variable as an ‘object’. That way, the variable can represent a sequence as well as an atom.

Sequences can contain other sequences and atoms. It can be subscripted & sliced. Any calculation performed on a sequence will be performed on all of its elements. Any calculation with two sequences requires the sequences to be of the same length. It will then perform the calculation with the respective elements of each sequence. The result will be a sequence of the same length, containing the results of each individual calculation. This also occurs when you compare two sequences, or when you compare a sequence with an atom. Here is an example, which might make things more clear for you:

Sequence ‘foo’ contains:

1, 2, 3, 4, 5, 6

‘foo’ adding 2 makes:

3, 4, 5, 6, 7, 8

‘foo’ adding ‘foo’ makes:

6, 8, 10, 12, 14, 16

‘foo’ < 10 evaluates:

1,1,0,0,0,0

Sequence ‘bar’ contains:

5,5,5

Slicing bar from 1 to 2 adding 3 makes bar:

8,8,5

The 2nd element of ‘foo’ adding bar makes foo:

1, { 10, 10, 7 }, 3, 4, 5, 6

Foo adding 4 makes foo:

5, {14, 14, 11 }, 7, 8, 9, 10

Characters are considered atoms, strings are considered sequences with atoms and arrays are considered sequences with sequences and eventually atoms. Sequences need not be pre-build like most languages do with arrays. They can however grow and shrink in real-time. You have built-in functions to append and ‘prepend’ elements to a sequence and you have the ‘&’ operator to combine two sequences or a sequence and an atom. You can only slice and subscript variables, but not expressions like a function result or an evaluation. You would be discarding returned information, which is not allowed. It usually is illegal to slice or subscript a sequence out of its bounds. However there are certain cases where this is allowed, for example when you slice from the first element to last element minus 1, which would sometimes mean, slicing from ‘1’ to ‘-1’. That expression would be legal. There are more cases like this where Euphoria shows off its elegance. But you have to take my word for it.

Debugging

First, we will discuss error prevention. Syntax errors are avoided by using straightforward English words. Even statement blocks begin with ‘do’ and end with ‘end function/procedure/type/while/for’.

Custom types can be used to avoid logical errors. Logical errors can usually be blamed at certain variables containing values that they are not supposed to have, which sometimes result in a logical- and sometimes in a run-time error. Types are one-argument-functions, which name you can use to declare a variable. Whenever the value of the variable changes the function is called and a type-check error will occur when that function returns false. You can use such a function to make sure that a certain variable contains at least a legal value if not the desired value. You can turn this type checking on and off at the top-level.

If an error does occur, you will get a nice English message from Euphoria, and a file named ‘EX.ERR’ is generated which contains a list of all variables and their values in a friendly and readable format. If you had tracing on you will also find the last 25 lines traced by the interpreter. Both the file and the message will have a suggestion to fix the error if appropriate.

You can also trace your program, lookup some values of variables, and see your program working step by step. You can turn tracing on and off through a statement, so you can determine at run-time if you want to go into trace mode. You could for example check a variable for that value that seems to generate some error and then activate the trace mode. You have to specify which sections you want to trace. Therefore, you do not have to step through code that already works. Those lines excluded in trace-mode will be executed without waiting for a key-press. It seems to me, that Euphoria's tracing capabilities are quite extensive and puts other tracers in a shame. The trace-mode even has syntax coloring!

Platforms

Currently, there are two platforms available: Win32 and Dos32. Both run in 32-bit protected mode and have access to all the computers memory: conventional, extended and virtual. The Dos32 platform will make its own swap-file for virtual memory if it is not running under Windows 95. The different platforms are provided within one package. It will contain only two executables. These are the interpreters for each platform. There are more tools available, but they are all provided as Euphoria source code and can be executed by either interpreter. You will find many example programs, a complete developing environment and some other useful tools.

The Dos32 platform has platform-specific routines for manual allocation, de-allocation, poking, peeking and calling machine code. The Win32 platform has platform-specific routines for message-boxes, creating windows and calling DLL's. Thankfully, extensive libraries to do all the window-magic are already available. You really do not want to write a windows-based program by manually calling zillions of DLL functions.

All programs not using platform-specific routines will work on both platforms. Platform specific routines will not generate an error on the other platform unless they are actually executed. You can lookup the platform by calling the platform function and choose which statement you want to execute based upon the value returned by the platform function.

 

Distribution

You can distribute your programs royalty-free in three ways. You can provide the source code and the public domain version of the interpreter. This is quite an efficient way if you have multiple programs.

However, if you do not want people to see the source code, you could shroud your program. Shrouding will combine the main program file and all include files into one file. All keywords will be tokenized, all comments removed and all variables and local routine names will be renamed to short cryptic names. You can even optionally hide all the strings and have your code encrypted.

In addition, if you only have one program to distribute, you could make an executable by binding it. Binding will combine the shrouded version of your program with the interpreter into one executable.

Conclusion

Any programming style is possible due to the flexibility of sequences. You could for example, program in a truly object oriented manner by keeping all the declarations within a file local except for one global function, named after the class. That function gets a message as argument, and uses handles for different instances. The instance-specific data of those instances can be looked up in a local sequence with the handle. Nevertheless, there are many more (practical) ways to program object oriented in Euphoria.

Euphoria can serve as a great teaching language, hiding all the pointers and machine specific garbage, so you can concentrate on algorithms and programming styles.

Euphoria is a great scripting language, because the syntax is almost completely English. You do not need to use any weird format. You are not forced to use routines. You do not need to compile.

Euphoria is great for small programs. You can quickly make solid, safe code in Euphoria fast, that is easy maintainable and does not need extensive debugging and bug-checking before you can be certain it will work.

Euphoria is great for big commercial programs. Those pieces that need the extra performance compiled languages give you, can be coded in machine code or put in a DLL. Your program will be developed fast, and there will be little time needed to catch all the bugs. Consider a bug-free program developed in one-fifth of the time it would take in C++. Not to mention all the time spent on getting those damn bugs out. I do not have to tell you how much money this can save a company. In addition, the company's name will be known for its solid programs. Your programs need not be followed by 200 bug-fixes later. Because Euphoria code is so generic, you can use your code repeatedly. The executable file will be relatively small. It will be almost impossible for someone to hack your program. And, as stated before, you can distribute your program royalty-free.

Because of its simplicity and lack of numerous "bells and whistles", Euphoria is often dismissed by professional and amateur programmers. There are currently only a small number of users worldwide. That means there are relatively few people who can maintain your Euphoria code, something most clients do not appreciate. The only way this situation can change is for more people to begin using Euphoria.

 

More information

"The Official Euphoria Programming Page":

http://www.RapidEuphoria.com

"Pete’s Euphoria Zone":

http://www.harborside.com/home/x/xseal/euphoria/

"Irv’s Euphoria Archive":

http://www.mindspring.com/~mountains/

"A beginners guide to Euphoria":

http://www.geocities.com/SiliconValley/Vista/4346/

 

Author

The article has been written by a 16 years Old Dutch Euphorian using some suggestions that Irv Mullins made. This article may be freely published in unchanged form. Although I would appreciate being notified first.

Ralf Nieuwenhuijsen

Nieuwen@xs4all.nl