The Complete Beginner's Guide to Programming with Jac#
Welcome to Programming! This guide will teach you how to program using Jac as your first programming language. No prior experience required. We'll start from the absolute basics and build up to advanced concepts step by step.
Table of Contents#
- Introduction: What is Programming?
- Setting Up: Your First Program
- The Basics: Variables and Data
- Making Decisions: Control Flow
- Repeating Actions: Loops
- Organizing Code: Functions
- Collections: Working with Multiple Values
- Grouping Things: Classes and Objects
- Where to Go Next
1. Introduction: What is Programming?#
Programming is giving instructions to a computer. Just like you might give directions to a friend ("turn left, then go straight"), you give instructions to a computer using a programming language.
Why Jac?#
Jac is special because it teaches you two ways of thinking:
- Traditional Programming - Like most languages (Python, JavaScript, Java)
- Object-Spatial Programming (OSP) - A new way to think about how data and computation work together
Think of it this way:
- Traditional Programming: You call a restaurant and order food to be delivered to you
- Object-Spatial Programming: You send a robot to visit different restaurants and collect food
Both get you fed, but they work differently! This guide teaches you the first: the programming fundamentals every language shares. Once you have those, Object-Spatial Programming teaches you the second.
2. Setting Up: Your First Program#
Every Jac program needs a place to start. We use a special block called with entry:
What's happening here?
with entry- This is where your program startsprint()- This is a function that displays text on the screen"Hello, World!"- This is text (called a string);- Every instruction ends with a semicolon{}- Curly braces group instructions together
Try it yourself: Change "Hello, World!" to your name!
3. The Basics: Variables and Data#
3.1 What is a Variable?#
A variable is like a labeled box where you store information. You give it a name, and you can put different things in it.
Lines starting with # are comments - they're notes for humans, the computer ignores them.
3.2 Types of Data#
Just like in real life, data comes in different types:
Text (Strings)#
Strings go inside quotes: "like this" or 'like this'
Numbers (Integers)#
Whole numbers with no decimal point.
Numbers (Floats)#
Numbers with decimal points.
True or False (Booleans)#
Only two values: True or False (notice the capital letters!)
3.3 Type Annotations (Recommended!)#
You can tell Jac what type of data a variable should hold:
Pro tip: The f before a string lets you insert variables using {variable_name}
3.4 Doing Math#
You can calculate with numbers:
with entry {
# Basic math
sum = 5 + 3; # Addition: 8
difference = 10 - 4; # Subtraction: 6
product = 6 * 7; # Multiplication: 42
quotient = 20 / 4; # Division: 5.0
print(sum); # Shows: 8
print(product); # Shows: 42
# More operations
remainder = 17 % 5; # Modulo (remainder): 2
power = 2 ** 3; # Exponent: 8 (2³)
# Combined operations
total = (5 + 3) * 2; # Use parentheses like in math: 16
print(total);
}
3.5 Changing Variables#
Variables can change their value:
Common shortcuts:
x += 5meansx = x + 5(add 5)x -= 3meansx = x - 3(subtract 3)x *= 2meansx = x * 2(multiply by 2)x /= 4meansx = x / 4(divide by 4)
3.6 Practice Exercise#
Challenge: Create a program that calculates the area of a rectangle.
4. Making Decisions: Control Flow#
Programs need to make decisions based on conditions. This is where if, elif, and else come in.
4.1 The If Statement#
How it works:
if age >= 18- Check if age is greater than or equal to 18- If the condition is
True, run the code inside{} - If the condition is
False, skip the code inside{}
4.2 Comparison Operators#
These let you compare values:
| Operator | Meaning | Example |
|---|---|---|
> |
Greater than | x > 5 |
< |
Less than | x < 10 |
>= |
Greater than or equal | age >= 18 |
<= |
Less than or equal | score <= 100 |
== |
Equal to | name == "Alice" |
!= |
Not equal to | status != "done" |
Important: Use == to compare (not =). Use = to assign values!
4.3 If-Else#
What if you want to do something when the condition is False?
4.4 If-Elif-Else#
What about multiple conditions?
How it works:
- Check first
if- ifTrue, run its code and skip the rest - If first is
False, check firstelif - Keep checking until one is
True - If none are
True, runelseblock
4.5 Combining Conditions#
You can combine multiple conditions:
with entry {
age = 25;
has_license = True;
# AND - both must be true
if age >= 16 and has_license {
print("You can drive!");
}
# OR - at least one must be true
if age < 18 or age > 65 {
print("Discounted ticket price!");
}
# NOT - reverse the condition
if not has_license {
print("You need a license!");
}
}
4.6 Nested Ifs#
You can put if statements inside other if statements:
4.7 Practice Exercise#
Challenge: Write a program that checks if someone is a child (0-12), teenager (13-19), adult (20-64), or senior (65+).
5. Repeating Actions: Loops#
Loops let you repeat code multiple times without writing it over and over.
5.1 The While Loop#
Repeat code while a condition is True:
Warning: Make sure your condition eventually becomes False, or your loop will run forever!
5.2 The For Loop (Counting)#
When you know exactly how many times to repeat:
Breaking it down:
i = 0- Start at 0i < 5- Continue while i is less than 5i += 1- Add 1 to i each time
5.3 The For-In Loop (Iterating)#
Loop through items in a collection:
5.4 Breaking Out of Loops#
Sometimes you want to stop a loop early:
5.5 Skipping Iterations#
Skip to the next iteration without running the rest of the loop body:
5.6 Practice Exercises#
Challenge 1: Write a loop that prints all multiples of 3 from 3 to 30.
Challenge 2: Write a countdown from 10 to 1, then print "Blast off!"
6. Organizing Code: Functions#
Functions are reusable blocks of code that do specific tasks. Think of them as mini-programs within your program.
6.1 Creating Your First Function#
6.2 Functions with Parameters#
Make functions more flexible by giving them inputs:
Breaking it down:
name: str- This is a parameter (input): str- Type annotation (optional but recommended)- When you call
greet("Alice"),"Alice"becomes the value ofname
6.3 Multiple Parameters#
Functions can take multiple inputs:
6.4 Returning Values#
Instead of just printing, functions can send values back:
Breaking it down:
-> int- This function returns an integerreturn x + y;- Send this value back to whoever called the function- The returned value can be stored in a variable or used directly
6.5 Default Parameters#
Give parameters default values:
def greet(name: str = "friend", excited: bool = False) {
if excited {
print(f"HELLO, {name}!!!");
} else {
print(f"Hello, {name}.");
}
}
with entry {
greet(); # Uses defaults
greet("Alice"); # Uses name, default excited
greet("Bob", True); # Both specified
greet(excited=True, name="Eve"); # Named parameters
}
6.6 Why Use Functions?#
1. Avoid Repetition
Bad:
Good:
2. Break Down Complex Problems
def calculate_area(width: float, height: float) -> float {
return width * height;
}
def calculate_perimeter(width: float, height: float) -> float {
return 2 * (width + height);
}
def describe_rectangle(width: float, height: float) {
area = calculate_area(width, height);
perimeter = calculate_perimeter(width, height);
print(f"Rectangle: {width} x {height}");
print(f"Area: {area}");
print(f"Perimeter: {perimeter}");
}
with entry {
describe_rectangle(5.0, 3.0);
}
6.7 Practice Exercises#
Challenge 1: Write a function that checks if a number is even.
Challenge 2: Write a function that finds the maximum of two numbers.
7. Collections: Working with Multiple Values#
So far, we've stored single values in variables. But what if you want to store multiple related values?
7.1 Lists - Ordered Collections#
Lists hold multiple values in order:
7.2 Accessing List Items#
Each item has an index (position), starting at 0:
with entry {
fruits = ["apple", "banana", "cherry", "date"];
print(fruits[0]); # apple (first item)
print(fruits[1]); # banana (second item)
print(fruits[3]); # date (fourth item)
# Negative indices count from the end
print(fruits[-1]); # date (last item)
print(fruits[-2]); # cherry (second to last)
}
Visual:
graph LR
subgraph "fruits list"
A["0: apple<br/>-4"]
B["1: banana<br/>-3"]
C["2: cherry<br/>-2"]
D["3: date<br/>-1"]
A --- B --- C --- D
end
7.3 Modifying Lists#
with entry {
numbers = [1, 2, 3];
# Change an item
numbers[1] = 99;
print(numbers); # [1, 99, 3]
# Add to end
numbers.append(4);
print(numbers); # [1, 99, 3, 4]
# Insert at position
numbers.insert(0, 0); # Insert 0 at index 0
print(numbers); # [0, 1, 99, 3, 4]
# Remove by value
numbers.remove(99);
print(numbers); # [0, 1, 3, 4]
# Remove by index
numbers.pop(0); # Remove first item
print(numbers); # [1, 3, 4]
}
7.4 List Operations#
7.5 Looping Through Lists#
7.6 List Slicing#
Get a portion of a list:
with entry {
numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
# [start:end] - start is included, end is excluded
print(numbers[2:5]); # [2, 3, 4]
# [:end] - from beginning to end
print(numbers[:3]); # [0, 1, 2]
# [start:] - from start to end of list
print(numbers[7:]); # [7, 8, 9]
# [start:end:step] - with step size
print(numbers[0:9:2]); # [0, 2, 4, 6, 8]
}
7.7 Dictionaries - Key-Value Pairs#
Dictionaries store data as key-value pairs:
7.8 Looping Through Dictionaries#
7.9 Tuples - Immutable Lists#
Tuples are like lists, but they can't be changed after creation:
7.10 List Comprehensions - Powerful Shortcuts#
Create lists in one line:
with entry {
# Traditional way
squares = [];
for i = 0 while i < 5 with i += 1 {
squares.append(i ** 2);
}
print(squares); # [0, 1, 4, 9, 16]
# List comprehension way
squares = [i ** 2 for i in range(5)];
print(squares); # [0, 1, 4, 9, 16]
# With condition
evens = [i for i in range(10) if i % 2 == 0];
print(evens); # [0, 2, 4, 6, 8]
}
7.11 Practice Exercises#
Challenge 1: Create a list of your 5 favorite foods and print each one.
Challenge 2: Create a dictionary of 3 people with their ages, then print the oldest person.
8. Grouping Things: Classes and Objects#
Classes let you create your own custom types that bundle data and functions together.
8.1 What is a Class?#
Think of a class as a blueprint for creating objects.
Real-world analogy:
- Class: Blueprint for a car (defines what all cars have)
- Object: An actual car (a specific instance)
8.2 Creating Your First Class#
# Define the class (blueprint)
class Dog {
has name: str = "Unnamed";
has age: int = 0;
def bark {
print(f"{self.name} says Woof!");
}
}
with entry {
# Create objects (instances)
my_dog = Dog();
my_dog.name = "Buddy";
my_dog.age = 3;
your_dog = Dog();
your_dog.name = "Max";
your_dog.age = 5;
# Use the objects
my_dog.bark(); # Buddy says Woof!
your_dog.bark(); # Max says Woof!
print(f"{my_dog.name} is {my_dog.age} years old");
}
Breaking it down:
class Dog- Define a new type called Doghas name: str- Every Dog has a name (property/attribute)def bark- Every Dog can bark (method)self- Refers to the current objectDog()- Create a new Dog object
8.3 Constructors - Setting Initial Values#
Objects are automatically initialized with their has attributes as parameters:
8.4 Why Use Classes?#
1. Group Related Data
Instead of:
Use:
2. Bundle Data with Behavior
obj BankAccount {
has balance: float = 0.0;
def deposit(amount: float) {
self.balance += amount;
print(f"Deposited ${amount}. New balance: ${self.balance}");
}
def withdraw(amount: float) {
if amount <= self.balance {
self.balance -= amount;
print(f"Withdrew ${amount}. New balance: ${self.balance}");
} else {
print("Insufficient funds!");
}
}
}
with entry {
account = BankAccount();
account.deposit(100.0);
account.withdraw(30.0);
account.withdraw(80.0); # Insufficient funds!
}
8.5 Inheritance - Building on Existing Classes#
Create specialized versions of classes:
# Base object
obj Animal {
has name: str;
has age: int;
def speak {
print(f"{self.name} makes a sound");
}
}
# Specialized object
obj Dog(Animal) { # Dog inherits from Animal
has breed: str;
# Override parent method
def speak {
print(f"{self.name} barks: Woof!");
}
# New method specific to Dog
def fetch {
print(f"{self.name} fetches the ball!");
}
}
obj Cat(Animal) {
# Override parent method
def speak {
print(f"{self.name} meows: Meow!");
}
}
with entry {
dog = Dog(name="Buddy", age=3, breed="Labrador");
cat = Cat(name="Whiskers", age=2);
dog.speak(); # Buddy barks: Woof!
cat.speak(); # Whiskers meows: Meow!
dog.fetch(); # Buddy fetches the ball!
}
Inheritance lets you:
- Reuse code from parent classes
- Create specialized versions
- Override methods for custom behavior
- Add new methods to specialized classes
8.6 Real Example: A Simple Game Character#
obj Character {
has name: str;
has health: int = 100;
has strength: int = 10;
def attack(target: Character) {
damage = self.strength;
print(f"{self.name} attacks {target.name} for {damage} damage!");
target.take_damage(damage);
}
def take_damage(amount: int) {
self.health -= amount;
print(f"{self.name} has {self.health} health remaining");
if self.health <= 0 {
print(f"{self.name} has been defeated!");
}
}
}
obj Warrior(Character) {
def postinit {
self.strength = 20; # Warriors hit harder
}
}
obj Mage(Character) {
def postinit {
self.strength = 15;
}
def cast_spell(target: Character) {
damage = self.strength * 2; # Spells do double damage
print(f"{self.name} casts fireball at {target.name} for {damage} damage!");
target.take_damage(damage);
}
}
with entry {
warrior = Warrior(name="Conan");
mage = Mage(name="Gandalf");
warrior.attack(mage);
mage.cast_spell(warrior);
}
8.7 Practice Exercises#
Challenge 1: Create a Rectangle class with width and height, and methods to calculate area and perimeter.
obj Rectangle {
has width: float;
has height: float;
def area -> float {
return self.width * self.height;
}
def perimeter -> float {
return 2 * (self.width + self.height);
}
}
with entry {
rect = Rectangle(width=5.0, height=3.0);
print(f"Area: {rect.area()}");
print(f"Perimeter: {rect.perimeter()}");
}
Challenge 2: Create a Student class with name and a list of grades, plus a method to calculate average grade.
obj Student {
has name: str;
has grades: list = [];
def add_grade(grade: int) {
self.grades.append(grade);
}
def average -> float {
if len(self.grades) == 0 {
return 0.0;
}
return sum(self.grades) / len(self.grades);
}
}
with entry {
student = Student(name="Alice");
student.add_grade(90);
student.add_grade(85);
student.add_grade(92);
print(f"{student.name}'s average: {student.average()}");
}
Where to Go Next#
Congratulations! You now know the fundamentals that every programming language shares:
- Variables and data types
- Making decisions with
if,elif, andelse - Repeating actions with
whileandforloops - Organizing code into functions with parameters and return values
- Collections: lists, dictionaries, and tuples
- Grouping data and behavior with classes, objects, and inheritance
That is enough programming to start learning the ideas that belong to Jac itself. Here is the path we recommend:
Jac Fundamentals is your next stop. It covers the full language: the syntax you saw here in greater depth, plus modules, implementation separation, and the features this primer skipped.
Object-Spatial Programming introduces nodes, edges, and walkers. Everything you learned about objects carries over. Object-Spatial Programming builds on classes to let you connect objects into graphs and move computation through them.
Core Concepts explains the big picture: the properties that set Jac apart and why they matter.
When you are ready to build something real, follow the AI Day Planner tutorial. It is a guided project that takes you from a blank folder to a working AI-powered web application, using exactly the fundamentals you practiced here.
Take your time, experiment with every example, and keep the programs you write as you go. Small working programs are the best study notes you can have.
Happy coding!