Quick Start Guide

TGet up and running with NOPE-PRO in just 5 minutes! This guide assumes you've already installed NOPE-PRO.

Your First Result

Let's start with a simple example that shows the power of NOPE-PRO:

1using UnityEngine;
2using NOPE.Runtime.Core;
3using NOPE.Runtime.Core.Result;
4using NOPE.PRO.VisualDebugger;
5
6public class QuickStartExample : MonoBehaviour
7{
8    void Start()
9    {
10        // Traditional approach - exceptions and nulls everywhere!
11        // DON'T DO THIS:
12        /*
13        try {
14            var data = LoadData();
15            if (data != null) {
16                var parsed = int.Parse(data);
17                if (parsed > 0) {
18                    Debug.Log($"Success: {parsed}");
19                }
20            }
21        } catch (Exception e) {
22            Debug.LogError($"Failed: {e.Message}");
23        }
24        */
25
26        // NOPE-PRO approach - beautiful and safe!
27        LoadDataSafe()
28            .EnableDebug("QuickStart")  // Enable visual debugging!
29            .Bind(ParseNumber)          // Chain operations
30            .Ensure(n => n > 0, "Number must be positive")
31            .Match<Unit>(
32                onSuccess: value => { Debug.Log($"✅ Success: {value}"); return Unit.Value; },
33                onFailure: error => { Debug.LogError($"❌ Failed: {error}"); return Unit.Value; }
34            );
35    }
36
37    // Return Result instead of throwing exceptions
38    Result<string, string> LoadDataSafe()
39    {
40        string data = PlayerPrefs.GetString("testData", "");
41        
42        return string.IsNullOrEmpty(data) 
43            ? "No data found"  // Implicit conversion to Failure
44            : data;            // Implicit conversion to Success
45    }
46
47    // Parse safely without exceptions
48    Result<int, string> ParseNumber(string input)
49    {
50        return Result.Of(
51            () => int.Parse(input),
52            ex => $"Invalid number format: {input}"
53        );
54    }
55}

Key Concepts in 2 Minutes

1. Result<T, E> - No More Exceptions

1// Creating Results
2Result<int, string> success = 42;                          // Success
3Result<int, string> failure = "Something went wrong";      // Failure
4
5// Checking state
6if (success.IsSuccess)
7    Debug.Log($"Value: {success.Value}");
8
9// Pattern matching
10string message = failure.Match(
11    onSuccess: val => $"Got {val}",
12    onFailure: err => $"Error: {err}"
13);

2. Maybe<T> - No More Nulls

1// Creating Maybe values
2Maybe<string> hasValue = "Hello";              // Has value
3Maybe<string> noValue = Maybe<string>.None;    // No value
4
5// Safe operations
6Maybe<int> length = hasValue.Map(s => s.Length);  // Maybe(5)
7
8// Pattern matching
9string result = noValue.Match(
10    onValue: val => $"Found: {val}",
11    onNone: () => "Not found"
12);

3. Chaining Operations

1// Chain multiple operations elegantly
2GetPlayerId()
3    .EnableDebug("PlayerFlow")      // Track in visual debugger
4    .Bind(LoadPlayerData)           // Async operation
5    .Map(player => player.Score)    // Transform
6    .Ensure(score => score >= 0, "Invalid score")
7    .Tap(score => Debug.Log($"Score: {score}"))  // Side effect
8    .Match<Unit>(
9        onSuccess: score => { ApplyScore(score); return Unit.Value; },
10        onFailure: error => { HandleError(error); return Unit.Value; }
11    );

Visual Debugging in Action

With NOPE_PRO_DEBUG enabled, use the Flow Debugger window (Window → NOPE → Flow Debugger) for detailed inspection:

Common Patterns

Safe Division

1Result<float, string> Divide(float a, float b)
2{
3    return b == 0
4        ? "Cannot divide by zero"
5        : a / b;
6}
7
8public void DivideSafely()
9{
10    // Usage
11    var result = Divide(10, 2)
12        .Match(
13            success => $"Result: {success}",
14            error => $"Error: {error}"
15        );
16    
17    // Output the result
18    // On success: "Result: 5"
19    // On error: "Error: Cannot divide by zero"
20    Debug.Log(result);
21}

Loading Game Data

1public Result<GameConfig, string> LoadConfig()
2{
3    return LoadFromDisk("config.json")
4        .Bind(ParseJson<GameConfig>)
5        .Ensure(config => config.Version > 0, "Invalid config version")
6        .Map(config =>
7        {
8            config.LoadTime = Time.time;
9            return config;
10        });
11}

Next Steps

Congratulations! You've learned the basics of NOPE-PRO. Here's what to explore next:

  1. Core Concepts - Deep dive into Railway-Oriented Programming
  2. Basic Usage Tutorial - Comprehensive walkthrough
  3. Visual Debugger Guide - Master the debugging tools
  4. API Reference - Complete method documentation

Quick Reference Card

1// Result<T,E> Creation
2Result<int, string> r1 = 42; // Success
3Result<int, string> r2 = "error"; // Failure
4var r3 = Result.SuccessIf(
5    condition: (1 > 0), // If condition is true, returns success result
6    successValue: "Success", // Success value
7    error: "Failure"); // Failure value
8
9var r4 = Result.Of(
10    func: () => SomeRiskyMethod(),
11    errorConverter: ex => ex.Message);
12
13
14Result<int, string> result = 0;
15// Transformations
16result.Map(x => x * 2); // Transform value
17result.Bind(x => LoadMore(x)); // Chain Results
18result.MapError(e => $"Context: {e}"); // Transform error
19result.Ensure(x => x > 0, "Must be positive"); // Add validation
20
21// Side Effects
22result.Tap(x => Debug.Log(x)); // On success, log value
23result.Match( // Handle both
24    onSuccess: x =>
25    {
26        Debug.Log($"Success: {x}");
27        return "Success handled";
28    },
29    onFailure: e =>
30    {
31        Debug.LogError($"Error: {e}");
32        return "Error handled";
33    }
34);
35
36// Maybe<T> Creation
37Maybe<int> m1 = 42; // Has value
38Maybe<int> m2 = Maybe<int>.None; // No value
39
40Maybe<int> maybe = 123;
41// Maybe Operations
42maybe.Map(x => x * 2); // Transform
43maybe.Where(x => x > 0); // Filter
44maybe.Or(0); // Provide fallback default value