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

GOTCHAS

Overview

Every programming language has gotchas. Those “wat” moments that make us all laugh when someone does a presentation on them. They often shoot to the top of sites like Hacker News and Reddit. It’s all in good fun, except, it isn’t. Each of those gotchas and the laughs we get from them, hide someone’s pain. This chapter covers some common Pony gotchas that new Pony programmers often stumble across with painful results. Probably the best way to approach this chapter is to imagine each section has a giant flashing “DO NOT DO THIS” sign.

Divide by Zero

What’s 1 divided by 0? How about 10 divided by 0? What is the result you get in your favorite programming language? In math, divide by zero is undefined. There is no answer to that question as the expression 1⁄0 has no meaning. In many programming languages, the answer is a runtime exception that the user has to handle. In Pony, things are a bit different. Divide by zero in Pony In Pony, integer division by zero results in zero.

Garbage Collection

There’s a common GC anti-pattern that many new Pony programmers accidentally stumble across. Usually, this results in a skyrocketing of memory usage in their test program and questions on Zulip as to why Pony isn’t working correctly. It is, in fact, working correctly, albeit not obviously. Garbage Collection in the world at large Garbage collection, in most languages, can run at any time. Your program can be paused so that memory can be freed up.

Scheduling

The Pony scheduler is not preemptive. This means that your actor has to yield control of the scheduler thread in order for another actor to execute. The normal way to do this is for your behavior to end. If your behavior doesn’t end, you will continue to monopolize a scheduler thread and bad things will happen. FFI and monopolizing the scheduler An easy way to monopolize a scheduler thread is to use the FFI facilities of Pony to kick off code that doesn’t return for an extended period of time.

Function Call Side Effects

Consider the following code: class Foo fun fn(x: U64) => None actor Main new create(env: Env) => var x: U64 = 0 try foo()?.fn(x = 42) end env.out.print(x.string()) fun foo(): Foo ? => error What do you think it will print? Probably 0 right? Or maybe you realized this code is in the gotchas section so it must be 42. If you went with 42, you’d be right. Why?

Recursion

Recursive functions in Pony can cause many problems. Every function call in a program adds a frame on the system call stack, which is bounded. If the stack grows too big it will overflow, usually crashing the program. This is an out-of-memory type of error and it cannot be prevented by the guarantees offered by Pony. If you have a heavy recursive algorithm, you must take some precautions in your code to avoid stack overflows.