Pony Tutorial
Opens in a new window Opens an external site Opens an external site in a new window
  • Getting Started
    • Overview
    • What You Need
    • Hello World: Your First Pony Program
    • Hello World: How It Works
  • Types
    • Overview
    • The Pony Type System at a Glance
    • Classes
    • Primitives
    • Actors
    • Traits and Interfaces
    • Structs
    • Type Aliases
    • Type Expressions
  • Expressions
    • Overview
    • Literals
    • Variables
    • Operators
    • Arithmetic
    • Control Structures
    • Methods
    • Errors
    • Equality in Pony
    • Sugar
    • Object Literals
    • Partial Application
  • Reference Capabilities
    • Overview
    • Reference Capabilities
    • Reference Capability Guarantees
    • Consume and Destructive Read
    • Recovering Capabilities
    • Aliasing
    • Passing and Sharing References
    • Capability Subtyping
    • Combining Capabilities
    • Arrow Types aka Viewpoints
    • Reference Capability Matrix
  • Object Capabilities
    • Overview
    • Object Capabilities
    • Trust Boundary
  • Generics
    • Overview
    • Generics and Reference Capabilities
    • Constraints
  • Pattern Matching
    • Overview
    • Match Expressions
    • As Operator
  • Packages
    • Overview
    • Package System
    • Use Statement
    • Standard Library
  • Testing
    • Overview
    • Testing with Ponytest
  • C FFI
    • Overview
    • Calling C from Pony
    • Linking to C Libraries
    • C ABI
    • Callbacks
  • Gotchas
    • Overview
    • Divide by Zero
    • Garbage Collection
    • Scheduling
    • Function Call Side Effects
    • Recursion
  • Where Next?
    • Overview
  • Appendices
    • Overview
    • PONYPATH
    • Lexicon
    • Symbol Lookup Cheatsheet
    • Keywords
    • Examples
    • Whitespace
    • Compiler Arguments
    • Memory Allocation at Runtime
    • Garbage Collection with Pony-ORCA
    • Platform-dependent code
    • A Short Guide to Pony Error Messages
    • Program Annotations
    • Serialisation

TYPES

Overview

Pony’s type system is what makes it special. There’s plenty to love about it otherwise but, in the end, it’s the type system that contains much of what makes Pony novel. In this chapter, we are going to explore the basics of the type system. If you worked with a statically typed language before, there shouldn’t be anything surprising to you. By the time you’ve finished this chapter, you should have a handle on basics of the Pony type system.

The Pony Type System at a Glance

Pony is a statically typed language, like Java, C#, C++, and many others. This means the compiler knows the type of everything in your program. This is different from dynamically typed languages, such as Python, Lua, JavaScript, and Ruby. Static vs Dynamic: What’s the difference? In both kinds of language, your data has a type. So what’s the difference? With a dynamically typed language, a variable can point to objects of different types at different times.

Classes

Just like other object-oriented languages, Pony has classes. A class is declared with the keyword class, and it has to have a name that starts with a capital letter, like this: class Wombat Do all types start with a capital letter? Yes! And nothing else starts with a capital letter. So when you see a name in Pony code, you will instantly know whether it’s a type or not.

Primitives

A primitive is similar to a class, but there are two critical differences: A primitive has no fields. There is only one instance of a user-defined primitive. Having no fields means primitives are never mutable. Having a single instance means that if your code calls a constructor on a primitive type, it always gets the same result back (except for built-in “machine word” primitives, covered below). What can you use a primitive for?

Actors

An actor is similar to a class, but with one critical difference: an actor can have behaviours. Behaviours A behaviour is like a function, except that functions are synchronous and behaviours are asynchronous. In other words, when you call a function, the body of the function is executed immediately, and the result of the call is the result of the body of the function. This is just like method invocation in any other object-oriented language.

Traits and Interfaces

Like other object-oriented languages, Pony has subtyping. That is, some types serve as categories that other types can be members of. There are two kinds of subtyping in programming languages: nominal and structural. They’re subtly different, and most programming languages only have one or the other. Pony has both! Nominal subtyping This kind of subtyping is called nominal because it is all about names. If you’ve done object-oriented programming before, you may have seen a lot of discussion about single inheritance, multiple inheritance, mixins, traits, and similar concepts.

Structs

A struct is similiar to a class. There’s a couple very important differences. You’ll use classes throughout your Pony code. You’ll rarely use structs. We’ll discuss structs in more depth in the C-FFI chapter of the tutorial. In the meantime, here’s a short introduction to the basics of structs. Structs are “classes for FFI” A struct is a class like mechanism used to pass data back and forth with C code via Pony’s Foreign Function Interface.

Type Aliases

A type alias is just a way to give a different name to a type. This may sound a bit silly: after all, types already have names! However, Pony can express some complicated types, and it can be convenient to have a short way to talk about them. We’ll give a couple examples of using type aliases, just to get the feel of them. Enumerations One way to use type aliases is to express an enumeration.

Type Expressions

The types we’ve talked about so far can also be combined in type expressions. If you’re used to object-oriented programming, you may not have seen these before, but they are common in functional programming. A type expression is also called an algebraic data type. There are three kinds of type expression: tuples, unions, and intersections. Tuples A tuple type is a sequence of types. For example, if we wanted something that was a String followed by a U64, we would write this: