Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ node_modules/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
phel-error.log

.DS_Store
Thumbs.db
Expand Down
85 changes: 85 additions & 0 deletions content/documentation/arithmetic.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,24 @@ All arithmetic operators are entered in prefix notation.
(+ 1 (* 2 2) (/ 10 5) 3 4 (- 5 6)) # Evaluates to 13
```

{% php_note() %}
Phel uses prefix notation (operator comes first) instead of PHP's infix notation:

```php
// PHP - infix notation
1 + (2 * 2) + (10 / 5) + 3 + 4 + (5 - 6);

// Phel - prefix notation
(+ 1 (* 2 2) (/ 10 5) 3 4 (- 5 6))
```

This allows operators to accept any number of arguments and eliminates operator precedence concerns.
{% end %}

{% clojure_note() %}
Arithmetic works exactly like Clojure—prefix notation with variadic support for most operators.
{% end %}

Some operators support zero, one or multiple arguments.

```phel
Expand All @@ -34,6 +52,27 @@ Some operators support zero, one or multiple arguments.
(/ 24 4 2) #Evaluates to 3
```

{% php_note() %}
Phel's variadic operators are more flexible than PHP's:

```php
// PHP - requires at least two operands
1 + 2 + 3 + 4 + 5;
// Can't do this: +(); <- syntax error

// Phel - supports 0, 1, or many operands
(+) # 0 (identity)
(+ 1) # 1 (identity)
(+ 1 2 3 4 5) # 15 (sum of all)
```

**Useful patterns:**
- `(+)` returns the additive identity (0)
- `(*)` returns the multiplicative identity (1)
- `(- x)` negates a number
- `(/ x)` computes the reciprocal
{% end %}

Further numeric operations are `%` to compute the remainder of two values and `**` to raise a number to the power. All numeric operations can be found in the API documentation.

Some numeric operations can result in an undefined or unrepresentable value. These values are called _Not a Number_ (NaN). Phel represents these values by the constant `NAN`. You can check if a result is NaN by using the `nan?` function.
Expand All @@ -44,6 +83,24 @@ Some numeric operations can result in an undefined or unrepresentable value. The
(nan? NAN) # true
```

{% php_note() %}
NaN handling is similar to PHP:

```php
// PHP
is_nan(1); // false
is_nan(log(-1)); // true
is_nan(NAN); // true

// Phel
(nan? 1) # false
(nan? (php/log -1)) # true
(nan? NAN) # true
```

The `%` operator for remainder and `**` for exponentiation work like PHP's `%` and `**` operators.
{% end %}

## Bitwise Operators

Phel allows the evaluation and manipulation of specific bits within an integer.
Expand Down Expand Up @@ -80,3 +137,31 @@ Phel allows the evaluation and manipulation of specific bits within an integer.
(bit-test 0b1011 0) # Evaluates to true
(bit-test 0b1011 2) # Evaluates to false
```

{% php_note() %}
Phel provides named functions for bitwise operations instead of PHP's operators:

```php
// PHP bitwise operators
0b1100 & 0b1001; // AND
0b1100 | 0b1001; // OR
0b1100 ^ 0b1001; // XOR
~0b0111; // NOT
0b1101 << 1; // Left shift
0b1101 >> 1; // Right shift

// Phel named functions
(bit-and 0b1100 0b1001)
(bit-or 0b1100 0b1001)
(bit-xor 0b1100 0b1001)
(bit-not 0b0111)
(bit-shift-left 0b1101 1)
(bit-shift-right 0b1101 1)
```

Phel also provides additional bit manipulation functions not available in PHP: `bit-set`, `bit-clear`, `bit-flip`, and `bit-test`.
{% end %}

{% clojure_note() %}
Bitwise operators work exactly like Clojure's—same function names and behavior for bit manipulation.
{% end %}
117 changes: 106 additions & 11 deletions content/documentation/basic-types.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,38 @@ weight = 2

## Nil, True, False

Nil, true and false are literal constants. In Phel, `nil` is the same as `null` in PHP. Phel's `true` and `false` are the same as PHP's `true` and `false`.
Nil, true and false are literal constants.

```phel
nil
true
false
```

In Phel, only `false` and `nil` are falsy. Everything else is truthy—including `0`, `""`, and `[]`.

```phel
# Truthiness examples
(if nil "yes" "no") # => "no" (nil is falsy)
(if false "yes" "no") # => "no" (false is falsy)
(if 0 "yes" "no") # => "yes" (0 is truthy!)
(if "" "yes" "no") # => "yes" (empty string is truthy!)
(if [] "yes" "no") # => "yes" (empty vector is truthy!)
```

{% php_note() %}
In PHP, `nil` is the same as `null`, and `true`/`false` are the same. However, truthiness works differently:

**PHP**: `0`, `""`, `[]`, `null`, and `false` are all falsy
**Phel**: Only `false` and `nil` are falsy

This means `if (0)` in PHP is false, but `(if 0 ...)` in Phel is true!
{% end %}

{% clojure_note() %}
Truthiness is the same as Clojure—only `false` and `nil` are falsy.
{% end %}

## Symbol

Symbols are used to name functions and variables in Phel.
Expand All @@ -26,7 +50,7 @@ my-module/my-function

## Keywords

A keyword is like a symbol that begins with a colon character. However, it is used as a constant rather than a name for something.
A keyword is like a symbol that begins with a colon character. However, it is used as a constant rather than a name for something. Keywords are interned and fast for equality checks.

```phel
:keyword
Expand All @@ -36,6 +60,35 @@ A keyword is like a symbol that begins with a colon character. However, it is us
::
```

Keywords are commonly used as map keys:

```phel
# Map with keyword keys
{:name "Alice" :email "[email protected]"}

# Accessing map values with keywords
(get {:name "Alice" :age 30} :name) # => "Alice"
(:name {:name "Alice" :age 30}) # => "Alice" (keywords are functions!)
```

{% php_note() %}
Keywords are like string constants, but more efficient for map keys. Use keywords instead of strings for map keys:

```phel
# Less idiomatic:
{"name" "Alice" "age" 30}

# Idiomatic:
{:name "Alice" :age 30}
```

Keywords are interned (only one instance exists in memory), making equality checks very fast.
{% end %}

{% clojure_note() %}
Keywords work exactly like in Clojure—they're interned, fast for equality checks, and self-evaluate.
{% end %}

## Numbers

Phel supports integers and floating-point numbers. Both use the underlying PHP implementation. Integers can be specified in decimal (base 10), hexadecimal (base 16), octal (base 8) and binary (base 2) notations. Binary, octal and hexadecimal formats may contain underscores (`_`) between digits for better readability.
Expand Down Expand Up @@ -69,9 +122,7 @@ Phel supports integers and floating-point numbers. Both use the underlying PHP i

## Strings

Strings are surrounded by double quotes. They almost work the same as PHP double-quoted strings. One difference is that the dollar sign (`$`) must not be escaped. Internally, Phel strings are represented by PHP strings. Therefore, every PHP string function can be used to operate on the string.

Strings can be written over multiple lines. The line break character is then ignored by the reader.
Strings are surrounded by double quotes. The dollar sign (`$`) does not need to be escaped.

```phel
"hello world"
Expand All @@ -89,9 +140,28 @@ string."

"Hexadecimal notation is supported: \x41"

"Unicodes can be encoded as in PHP: \u{1000}"
"Unicodes can be encoded: \u{1000}"
```

String concatenation and conversion using `str`:

```phel
(str "Hello" " " "World") # => "Hello World"
(str "The answer is " 42) # => "The answer is 42"
```

{% php_note() %}
Phel strings are PHP strings internally, so you can use all PHP string functions:

```phel
(php/strlen "hello") # => 5
(php/strtoupper "hello") # => "HELLO"
(php/str_replace "o" "0" "hello") # => "hell0"
```

Strings work almost the same as PHP double-quoted strings, with one difference: the dollar sign (`$`) doesn't need escaping.
{% end %}

## Lists

A list is a sequence of whitespace-separated values surrounded by parentheses.
Expand All @@ -118,17 +188,42 @@ A vector in Phel is an indexed data structure. In contrast to PHP arrays, Phel v

## Maps

A map is a sequence of whitespace-separated key/value pairs surrounded by curly braces, wherein the key and value of each key/value pair are separated by whitespace. There must be an even number of items between curly braces or the parser will signal a parse error. The sequence is defined as key1, value1, key2, value2, etc.
A map is a sequence of whitespace-separated key/value pairs surrounded by curly braces. The sequence is defined as key1, value1, key2, value2, etc. There must be an even number of items.

```phel
{} # same as (hash-map)
{:key1 "value1" :key2 "value2"}
{'(1 2 3) '(4 5 6)}
{[] []}
{1 2 3 4 5 6}

# Any type can be a key
{'(1 2 3) '(4 5 6)} # Lists as keys
{[] []} # Vectors as keys
{1 2 3 4 5 6} # Numbers as keys

# Common pattern: keywords as keys
{:name "Alice" :age 30 :email "[email protected]"}
```

{% php_note() %}
Unlike PHP associative arrays, Phel maps:
- Can have **any type** as keys (not just strings/integers): vectors, lists, or even other maps
- Are **immutable**: operations return new maps without modifying the original
- Are **not** PHP arrays internally—they're their own data structure

```phel
# PHP:
$map = ['name' => 'Alice'];
$map['name'] = 'Bob'; // Mutates in place

# Phel:
(def map {:name "Alice"})
(def new-map (assoc map :name "Bob")) # Returns new map
# map is still {:name "Alice"}
```
{% end %}

In contrast to PHP associative arrays, Phel maps can have any types of keys.
{% clojure_note() %}
Maps work exactly like Clojure maps, including support for any hashable type as keys.
{% end %}

## Sets

Expand Down
Loading
Loading