Is Scheme object oriented?

(Note:  We may earn commissions from products/services you click on.  This is at no extra cost to you.)

Table of Contents

Scheme is a well-known functional programming language. But it is not a clear object-oriented language. However, some scheme implementations feature inbuilt object-oriented extensions. Such scheme implementation includes XScheme, MacScheme, Oaklisp, Feel, and PC-Scheme.
But again, it is possible to interpret a closure as an object in Scheme for two reasons. First, there is the use of static binding of free names, and second, the first-class status of functions. Interpreting things in this manner makes it easy to regard some procedures defined as classes.
So, it’s possible to implement object-oriented programming in Scheme. Getting the correct extension and implementation makes the entire process very easy. So, you should conduct due diligence if you want to carry out object-oriented programming in Scheme.
MEROON is a powerful package written in Scheme, and it provides the basic facilities of an object-oriented programming style via three macros: define-generic, define-class, and define-method. Its inheritance is simple, and also it has simple dispatching generic functions that support multi-methods. Beyond that, it has reflective metaclasses. And it offers indexed fields that subsume Scheme vectors without inheritance restrictions.
Scheme Object Oriented Programming System (SCOOPS) is another handy tool. This package is an object system for a Scheme developed by Amitabh Srivastava. The package works well with first-class environments.
Keep in mind that the majority of implementations have CLOS-like systems, which may substantially differ in the type of syntax but being very close semantically.
Tiny CLOS implementation is for `kernelized’ CLOS but has a metaobject protocol. Tiny CLOS is much simpler than the CLOS found in `The Art of the Metaobject Protocol,’ weighing around 850 lines of code, plus (some) comments and documentation.
Virgo is another powerful tool, which serves as one library for objects in R7RS. The biggest advantage of Virgo is its portability; however, its concepts apply across various implementations.

Is Scheme object oriented
Is Scheme object oriented

Scheme programming language 

Scheme is a high-level language, general-purpose programming language. Scheme is used to carry out data structure operations, including lists, strings, and vectors. Besides, it can perform operations on more traditional data sets like characters and numbers. 

The banner usually placed on Scheme is its use for symbolic operations. However, it features a flexible control structure system and rich data types, making it a versatile programming language. That’s why Scheme is widely used across various industries. Precisely, Scheme has been used to write optimizing compilers, text editors, graphic packages, operating systems, numerical applications, expert systems, virtual reality systems, and financial analysis packages. 

Click this affiliate link to start your journey of exploring different programming languages.

While Scheme is a highly portable program, it only works across a similar scheme implementation version on various machines. The reason for this the machine dependencies in Scheme are hidden from the programmer. 

Scheme Syntax

a specific scheme program features variables, keywords, constant data(characters, numbers, strings, quoted, list, quoted numbers, and quoted symbols), structured forms, comments, and white spaces. 

The term identifier is used for variables, keywords, and symbols collectively, and they may be formed from digits, letters, and special characters like ?, ., !, +, $,/, etc., and other Unicode characters. Identifiers cant start with at (@) sign or a character that can start a number – plus (+) sign, a decimal point(.), minus (-)sign or digit. However, there are exceptions, i.e., +, -, and …; these are valid identifiers.

Scheme Naming Conventions

The naming conventions are designed to offer a high degree of regularity. They include: 

  • Predicate names ending in a question mark ( ? )
  • Type predicates are created from name pair, e.g., pair?
  • Names mostly begin with a prefix.
  • Procedure names that convert that convert an object type from one form to another are written as type1->type2.

A scheme system offers an interactive programming environment, which simplifies program development as well as experimentation. The interaction follows a “read-evaluate-print” cycle and is executed by a read-evaluate-print loop or REPL program. The program reads each expression typed, evaluates it, and prints its value.

So, you can type an expression and immediately see its value. That gives you the flexibility to define procedures and apply them to arguments to see how they work. What’s more, you can type the whole program with its sets of procedures and tests without leaving the Scheme system. 

Longer programs are more convenient, being typed into files using text editor, load it and then test it interactively. Good thing; you can load files with nonstandard procedure load. 

Scheme language examples

By now, you know that Scheme is imperative with a functional core based on lambda calculus. Parameters (functional programming) and assignment (imperative) perform the same role. But scheme functions are applied in arguments and return the answer. 

Scheme Programs Structure

Scheme programming deals with a function definition, and the programs don’t have imposed structures. Besides, there isn’t the primary function, and function definitions can be nested. The execution of scheme programs is done via submitting an expression for evaluation. 

Both functions and expressions are scripted similarly;

function_name arguments

Scheme resembles LISP, and data types are equal. So that means that what you can do to a particular data type can be applied to all other data types. This differs from most other languages, especially those having data types that for doing extraordinary things or those that are specially restricted. 

But there is a special restriction to functions because you can’t create a function without a name. by contrast, numbers have special rights in most languages since they can be used without names. 

Keyword lambda is used to create unnamed functions:

(lambda (x) (* x x)) -> a function

(define sq (lambda (x) (* x x))

(sq 9) -> 27

((lambda (x) (* x x)) 9) -> 27

((if (foo? x) * +) 2 3 4) -> if (foo? x) is true,

                                                                                                  then (* 2 3 4)

                                                                                                  else (+ 2 3 4)

Syntax

Scheme is syntactically close to the lambda calculus – you already know. 

Scheme Syntax

E in Expressions

K in Constants

I in Identifiers (variables)

E ::= K | I | (E_0 E^*) | (lambda (I^*) E2) | (define I E’)

When star `*’ follows a syntactic category, it indicates zero. Also, it can show more repetitions of elements of that category. As a result, Scheme allows lambda abstractions of more than one parameter. 

Scheme deviates from standard mathematical notation for functions. You can write functions in the form ({\em Function-name Arguments…}). On the other hand, the spaces and not comas separate {\em arguments}. 

Input-output expressions

The input is not passed as a parameter in Scheme, so it doesn’t readily support the functional form of interactive programming. However, you can readily perform such tasks through successive evaluations of inbuilt functions such as: 

  (+ 3 (read))

Higher-Order Functions

A higher-order function is a function that expects a function as a parameter or returns a function as a result. Scheme lacks an extensive repertoire of higher-order functions; however, {\tt apply} and {\tt map} are two inbuilt higher-order functions.

Scheme object system

Function objects (closure)represent functions at run time, and it represents the value of a lambda expression. All function objects have the following characteristics:

  • First-class objects
  • Do not have a name but can be bound to a name in a definition
  • It functions as closures by capturing free names in a context of a lambda expression, carries out static binding of free characters, 

As earlier stated, a pair of function syntax and values of free names represent closure. And you can apply a function object on actual parameters. Besides, you can pass it to a function and returned it as an outcome of another function. Still, you can organize it as a component of a data structure. 

The reason why function objects are called closures is that they return a function object captures and ‘closes around’ the free name that the function object depends on. This is a result of the use of static binding of free names. 

Classes and objects

You can interpret a function definition as a class, and it can also play a role of an object. Mainly, lambda expressions can be categorized as classes, while specific closures can be seen as objects. 

A data structure represents a class of objects, and the record-class facility supports aspects of object-classes. However, the support is not direct for other elements like an inheritance.

Scheme implementations have inbuilt extensions that also make it possible to create objects within its system. These contributions within the object system make it a versatile tool. Such extensions include:

Bryan’s Object System (BOS): this is a tiny object within Scheme and is based on generic functions and multiple inheritances. This package offers features similar to Tiny CLOS base and Meroon language but works faster than these languages; though it has been optimized – it lacks MOP. BOS runs on any modern Scheme implementation with minimum to no change. 

Yet Another Scheme Object System (YASOS): this tool uses delegation, but its style is pretty functional. Its implementations take into account multiple inheritances, but it’s much smaller than class-based object-oriented systems. 

MEROON: this package offers a programming style similar to what object-oriented programs offer define-generic, define-method, and define-class. Along with it comes the benefits of limited inheritance restrictions on fields subsuming vectors.  

Others include CLOS, Tiny CLOS, and Scheme Object Oriented Programming System.

Scheme code example

Understanding scheme code can be a little tricky, especially if you are a beginner. Though textbooks teach how to write the codes, the process is long but in-depth. Learning the coding from the online platform offers pretty straightforward since it uses examples. 

If you are interested in writing or knowing to write 

scheme code, ensure that:

  • You write a code that is read and understand, whether in part or as a whole. The code must be readable to both the author and the reader. That means you can encapsulate the code to make it more readable. Also, adhere to consistency.
  • The architecture and layout should be well-thought-out. The most complex part is the state – it comes with out-of-order operations, database inconsistencies, or might make the code too complicated. Your primary aim should the clarity of the codebase.

Scheme comes with all the qualities you need to write a clear, concise code quickly. First, it has a simpler syntax, i.e., s-expr – the code is the Abstract Syntax Tree. Though simple, the syntax is very powerful. Typically, creating a complex meta-class is much easier compared to other languages like python. 

Scheme’s multi-paradigm capability is what makes it one of the best programming languages. If you like, you can have mutability – functional or object-oriented programming. Since it is a functional programming language, it is easier to wrap your head around Scheme because you are sure that they can do some things. Thus, its function signature tells you what’s happening in and the outcome of each function. Additionally, if you want to debug, it is easier.

So, how can we use Scheme?

Basic calculations – enclose all functions using brackets (). For instance, if you want to add two numbers like 2 and 3, represent it as:

(+2 3)

‘+’ is the symbol, whereas 2 and 3 are the operator ‘+ parameters.’ 

The command follows ‘>,’ and it gives the output in bold. 

So, it will be:

> (+2 3)

If you use ‘;,’ anything that follows, it is usually a comment. If you are dealing with complex calculations, you can nest brackets – for instance:

> (* (+ 6 7) (- 7 1))

Lists – these are the principal aggregate types. Typical a list is a set of beaded cons cells, and its last element is ‘() denoting an empty list. you can create a list using the commend: 

> (list 3 4 5 6)

(3 4 5 6)

What are the four object-oriented principles?

When working with Object-oriented programming languages, programmers have a feeling of working on real-life entities. The programming languages typically have entities/ fields for storage of data/knowledge and perform various methods.  

To understand object-oriented programming, here are basic terminologies to understand:

  • Object: it’s the class’s working entity or class’s instance 
  • Class: it’s capability of an object 
  • Method: it’s essential in modifying class state, which applies in all class instances 
  • Instance: it’s the blueprint of the design 

Now, the 4 object-oriented programming principles are Encapsulation, Inheritance, Abstraction, and Polymorphism.

Encapsulation

This is the hiding of data implementation via restricting access to public methods. To achieve this, accessor methods are turned public while instance variables are made private. Ideally, the objects will maintain private state within a class. 

That means that other objects cannot directly access the state; instead, it is only possible to invoke public functions. An Object runs its state through the functions. Other classes cannot change it unless allowed explicitly. 

So, there are only two main aspects of encapsulation: 

  • Restrict access, i.e., preventing an object from accessing another object internal state
  • Namespaces/scopes – allowing a single name to have multiple meanings in different contexts 

From this summary, encapsulation is suitable for minimizing couplings between software components. Since most encapsulation mechanism has origins in non-object-oriented languages, object-oriented languages have additional encapsulation mechanisms.

Abstraction

Abstraction means selecting data from a larger data pool to show the relevant details only to the Object. Typically, an abstract is an idea that has no association with any instance. When using an abstract interface, you express an interface’s intention rather than the real implementation. 

In simple terms, one class’s inner details shouldn’t be known by another class to use it – knowing the interface is enough. 

Inheritance

This is when an object acquires all or some properties from another object. Inheritance comes with the advantage of reusability – you can reuse fields and methods of the existing class. Some programming language like Java offers multiple levels of inheritances – single, multilevel, multiple, hybrid and hierarchical.

Inheritances express a relationship between two objects as “is-a” and “has-a.” therefore, in derived classes, reusing an existing class code is very easy. Java uses the “is-a” concept based on class inheritance by using extends or interface implementation by using implements. 

There are two inheritances 

  • interface – it is vital in typed object-oriented languages. You can understand it better when applied in delegation-based design patterns
  • implementation inheritance – this Type varies with the Type of Object-oriented language. 

Polymorphism

Polymorphisms mean using a single name in different ways. But it is further classified in two – dynamic and static polymorphism. While static polymorphism is achieved via overloading, dynamic polymorphism, it achieved via overriding. 

Keep in mind; polymorphism is almost similar to inheritance. It allows using classes precisely as you used their parents without confusion – you can easily write a code to work as a superclass. It will work with any available subclass types. 

Scheme is important in the grander scheme of things as far as programming is concerned.  Click this affiliate link to start learning more about it.

What are Object-oriented examples?

Object-Oriented Programming (OOP) works on the principles of encapsulation, abstraction, inheritance, and polymorphism. The programming concepts offer users immense flexibility by giving them unlimited freedom to create objects and methods to handle such objects. 

The concept behind OOP is creating objects, re-suing them in the program, and manipulating these objects to get desirable results. The objects created contain both functions and data. The significant advantage of using Object-oriented programming concepts include:

  • It performs incredibly faster and is much easier to execute
  • Its structure for programs is clear. 
  • In C++, Object-oriented programming keeps the code DRY, i.e., “Don’t Repeat Yourself.” Besides, it makes it easier to maintain, modify and debug the code. 
  • It allows the creation of fully reusable applications with less code and shorter development time.

It’s clear; the focus of OOP is on objects, which developers manipulate instead of the logic needed to manipulate them. This programming concept is suitable for large, complex, and actively maintained or updated programs. 

Besides, considering how objects can be organized in an object-oriented program, the method benefits collaborative development – where groups are partitioned into groups. 

Programmers collect all the objects they need to manipulate as the first step in OOP. Additionally, the programmer identifies how things relate to each other, a process called data modeling. There are different types of objects – examples include physical entities like a human. You can describe a human being using their name and address. Another example can be a small computer program like widgets. 

After identifying an object, the programmer labels are based on a class of objects, which defines the type of data it contains and the logic sequence it manipulates. A distinct logic sequence is termed a method. A well-defined interface is termed messages, and it usually communicates with objects. 

Using an example of a car: the CAR takes the class’s point and has all properties/attributes that a car must have, including brand, model, and color, and the method is repaint. So, you can create an instance of a Car type object, myCar, to represent my specific car.

Each class has properties defined, sets their value to describe myCar. Setting these parameters should not affect class templates or objects. You can reuse the class to represent different numbers of cars.

A typical example is:

Object: myCar

Attributes

  • Colour: blue
  • Brand: BMW
  • Model: X7 (G07)

In many cars, a programmer can create a parent class for all cars to act as a blueprint, create child classes to represent the various subcategories, add unique properties, and create objects from the child class. 

Conclusion 

Scheme is a robust programming language considering it supports many paradigms. The object closures within Scheme return values from lambda expressions. These function objects are commonly called closures because the function objects will capture and close around a free name that the function object depends on because of the free names’ use of static binding. 

Scheme supports SRFI-9 records or R7RS records. Besides, R6RS provides records with a slightly different syntax. The records offer ways to make new types in Scheme. Additionally, the majority of schemes, alongside R6RS and R7RS, support libraries or modules that encapsulate such types.

Some scheme programmers prefer using these tools rather than the object-oriented programming concept to create their programs. However, that will depend much on the nature of the application they are making. Records provide Type and associated fields. Along with this comes a procedure that creates new objects for the Type while other procedures take the records as first arguments and give the Type’s needed operations. The library/module definition determines the ones exported to user code and those that remain private to the module/library implementation. 

If a records field is a procedure, it can have its private as closure. However, programmers most often want to use module definition for encapsulation and data hiding instead of closures. 

Luis Gillman
Luis Gillman

Hi, I Am Luis Gillman CA (SA), ACMA
I am a Chartered Accountant (SA) and CIMA (SA) and author of Due Diligence: A strategic and Financial Approach.

The book was published by Lexis Nexis on 2001. In 2010, I wrote the second edition. Much of this website is derived from these two books.

In addition I have published an article entitled the Link Between Due Diligence and Valautions.

Disclaimer: Whilst every effort has been made to ensure that the information published on this website is accurate, the author and owners of this website take no responsibility  for any loss or damage suffered as a result of relience upon the information contained therein.  Furthermore the bulk of the information is derived from information in 2018 and use therefore is at your on risk. In addition you should consult professional advice if required.