Files
wren/manual/language/methods.html
T
retoor 5a4054ec66 feat: add example scripts for argparse, bytes, dataset, html, markdown, uuid, wdantic, and web chat modules
Add comprehensive demo scripts showcasing the usage of multiple Wren modules including argument parsing, byte manipulation, in-memory dataset operations, HTML encoding/slugification, markdown-to-HTML conversion, UUID generation/validation, schema validation with wdantic, and a full web chat application with REST endpoints.
2026-01-24 22:40:22 +00:00

377 lines
14 KiB
HTML

<!DOCTYPE html>
<!-- retoor <retoor@molodetz.nl> -->
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Methods - Wren-CLI Manual</title>
<link rel="stylesheet" href="../css/style.css">
</head>
<body>
<button class="mobile-menu-toggle">Menu</button>
<div class="container">
<aside class="sidebar">
<div class="sidebar-header">
<h1><a href="../index.html">Wren-CLI</a></h1>
<div class="version">v0.4.0</div>
</div>
<nav class="sidebar-nav">
<div class="section">
<span class="section-title">Getting Started</span>
<ul>
<li><a href="../getting-started/index.html">Overview</a></li>
<li><a href="../getting-started/installation.html">Installation</a></li>
<li><a href="../getting-started/first-script.html">First Script</a></li>
<li><a href="../getting-started/repl.html">Using the REPL</a></li>
</ul>
</div>
<div class="section">
<span class="section-title">Language</span>
<ul>
<li><a href="index.html">Syntax Overview</a></li>
<li><a href="classes.html">Classes</a></li>
<li><a href="methods.html" class="active">Methods</a></li>
<li><a href="control-flow.html">Control Flow</a></li>
<li><a href="fibers.html">Fibers</a></li>
<li><a href="modules.html">Modules</a></li>
</ul>
</div>
<div class="section">
<span class="section-title">API Reference</span>
<ul>
<li><a href="../api/index.html">Overview</a></li>
<li><a href="../api/http.html">http</a></li>
<li><a href="../api/websocket.html">websocket</a></li>
<li><a href="../api/tls.html">tls</a></li>
<li><a href="../api/net.html">net</a></li>
<li><a href="../api/dns.html">dns</a></li>
<li><a href="../api/json.html">json</a></li>
<li><a href="../api/base64.html">base64</a></li>
<li><a href="../api/regex.html">regex</a></li>
<li><a href="../api/jinja.html">jinja</a></li>
<li><a href="../api/crypto.html">crypto</a></li>
<li><a href="../api/os.html">os</a></li>
<li><a href="../api/env.html">env</a></li>
<li><a href="../api/signal.html">signal</a></li>
<li><a href="../api/subprocess.html">subprocess</a></li>
<li><a href="../api/sqlite.html">sqlite</a></li>
<li><a href="../api/datetime.html">datetime</a></li>
<li><a href="../api/timer.html">timer</a></li>
<li><a href="../api/io.html">io</a></li>
<li><a href="../api/scheduler.html">scheduler</a></li>
<li><a href="../api/math.html">math</a></li>
</ul>
</div>
<div class="section">
<span class="section-title">Tutorials</span>
<ul>
<li><a href="../tutorials/index.html">Tutorial List</a></li>
<li><a href="../tutorials/http-client.html">HTTP Client</a></li>
<li><a href="../tutorials/websocket-chat.html">WebSocket Chat</a></li>
<li><a href="../tutorials/database-app.html">Database App</a></li>
<li><a href="../tutorials/template-rendering.html">Templates</a></li>
<li><a href="../tutorials/cli-tool.html">CLI Tool</a></li>
</ul>
</div>
<div class="section">
<span class="section-title">How-To Guides</span>
<ul>
<li><a href="../howto/index.html">How-To List</a></li>
<li><a href="../howto/http-requests.html">HTTP Requests</a></li>
<li><a href="../howto/json-parsing.html">JSON Parsing</a></li>
<li><a href="../howto/regex-patterns.html">Regex Patterns</a></li>
<li><a href="../howto/file-operations.html">File Operations</a></li>
<li><a href="../howto/async-operations.html">Async Operations</a></li>
<li><a href="../howto/error-handling.html">Error Handling</a></li>
</ul>
</div>
</nav>
</aside>
<main class="content">
<nav class="breadcrumb">
<a href="../index.html">Home</a>
<span class="separator">/</span>
<a href="index.html">Language</a>
<span class="separator">/</span>
<span>Methods</span>
</nav>
<article>
<h1>Methods</h1>
<p>Methods are the primary way to define behavior in Wren. They can be instance methods, static methods, getters, setters, or operators.</p>
<h2>Instance Methods</h2>
<p>Instance methods operate on a specific object:</p>
<pre><code>class Greeter {
construct new(name) {
_name = name
}
greet() {
return "Hello, %(_name)!"
}
greetWith(greeting) {
return "%(greeting), %(_name)!"
}
}
var g = Greeter.new("World")
System.print(g.greet()) // Hello, World!
System.print(g.greetWith("Hi")) // Hi, World!</code></pre>
<h2>Static Methods</h2>
<p>Static methods belong to the class rather than instances:</p>
<pre><code>class StringUtils {
static reverse(s) {
var result = ""
for (i in (s.count - 1)..0) {
result = result + s[i]
}
return result
}
static capitalize(s) {
if (s.count == 0) return s
return s[0].toString.toUpperCase + s[1..-1]
}
}
System.print(StringUtils.reverse("hello")) // olleh
System.print(StringUtils.capitalize("hello")) // Hello</code></pre>
<h2>Getters</h2>
<p>Getters are methods without parentheses that act like properties:</p>
<pre><code>class Temperature {
construct celsius(c) {
_celsius = c
}
celsius { _celsius }
fahrenheit { _celsius * 9 / 5 + 32 }
kelvin { _celsius + 273.15 }
}
var temp = Temperature.celsius(100)
System.print(temp.celsius) // 100
System.print(temp.fahrenheit) // 212
System.print(temp.kelvin) // 373.15</code></pre>
<h2>Setters</h2>
<p>Setters use the <code>=</code> suffix:</p>
<pre><code>class Box {
construct new(value) {
_value = value
}
value { _value }
value=(v) {
if (v &lt; 0) Fiber.abort("Value must be non-negative")
_value = v
}
}
var box = Box.new(10)
box.value = 20
System.print(box.value) // 20</code></pre>
<h2>Method Signatures</h2>
<p>Wren distinguishes methods by their signature (name + arity):</p>
<pre><code>class Example {
method { "no args" }
method() { "zero args with parens" }
method(a) { "one arg" }
method(a, b) { "two args" }
}
var e = Example.new()
System.print(e.method) // no args
System.print(e.method()) // zero args with parens
System.print(e.method(1)) // one arg
System.print(e.method(1, 2)) // two args</code></pre>
<h2>Block Arguments</h2>
<p>Methods can take a block as the last argument:</p>
<pre><code>class List {
static each(list, fn) {
for (item in list) {
fn.call(item)
}
}
static map(list, fn) {
var result = []
for (item in list) {
result.add(fn.call(item))
}
return result
}
}
var numbers = [1, 2, 3, 4, 5]
List.each(numbers) { |n|
System.print(n)
}
var doubled = List.map(numbers) { |n| n * 2 }
System.print(doubled) // [2, 4, 6, 8, 10]</code></pre>
<h2>Operator Overloading</h2>
<p>Classes can define custom behavior for operators:</p>
<h3>Binary Operators</h3>
<pre><code>class Vector {
construct new(x, y) {
_x = x
_y = y
}
x { _x }
y { _y }
+(other) { Vector.new(_x + other.x, _y + other.y) }
-(other) { Vector.new(_x - other.x, _y - other.y) }
*(scalar) { Vector.new(_x * scalar, _y * scalar) }
/(scalar) { Vector.new(_x / scalar, _y / scalar) }
==(other) {
return _x == other.x && _y == other.y
}
toString { "(%(_x), %(_y))" }
}
var a = Vector.new(1, 2)
var b = Vector.new(3, 4)
System.print((a + b).toString) // (4, 6)
System.print((a * 2).toString) // (2, 4)
System.print(a == b) // false</code></pre>
<h3>Available Operators</h3>
<table>
<tr>
<th>Operator</th>
<th>Signature</th>
<th>Description</th>
</tr>
<tr><td><code>+</code></td><td><code>+(other)</code></td><td>Addition</td></tr>
<tr><td><code>-</code></td><td><code>-(other)</code></td><td>Subtraction</td></tr>
<tr><td><code>*</code></td><td><code>*(other)</code></td><td>Multiplication</td></tr>
<tr><td><code>/</code></td><td><code>/(other)</code></td><td>Division</td></tr>
<tr><td><code>%</code></td><td><code>%(other)</code></td><td>Modulo</td></tr>
<tr><td><code>&lt;</code></td><td><code>&lt;(other)</code></td><td>Less than</td></tr>
<tr><td><code>&gt;</code></td><td><code>>(other)</code></td><td>Greater than</td></tr>
<tr><td><code>&lt;=</code></td><td><code>&lt;=(other)</code></td><td>Less or equal</td></tr>
<tr><td><code>&gt;=</code></td><td><code>>=(other)</code></td><td>Greater or equal</td></tr>
<tr><td><code>==</code></td><td><code>==(other)</code></td><td>Equality</td></tr>
<tr><td><code>!=</code></td><td><code>!=(other)</code></td><td>Inequality</td></tr>
<tr><td><code>&amp;</code></td><td><code>&amp;(other)</code></td><td>Bitwise AND</td></tr>
<tr><td><code>|</code></td><td><code>|(other)</code></td><td>Bitwise OR</td></tr>
<tr><td><code>^</code></td><td><code>^(other)</code></td><td>Bitwise XOR</td></tr>
<tr><td><code>&lt;&lt;</code></td><td><code>&lt;&lt;(other)</code></td><td>Left shift</td></tr>
<tr><td><code>&gt;&gt;</code></td><td><code>>>(other)</code></td><td>Right shift</td></tr>
<tr><td><code>..</code></td><td><code>..(other)</code></td><td>Inclusive range</td></tr>
<tr><td><code>...</code></td><td><code>...(other)</code></td><td>Exclusive range</td></tr>
</table>
<h3>Unary Operators</h3>
<pre><code>class Vector {
construct new(x, y) {
_x = x
_y = y
}
- { Vector.new(-_x, -_y) }
! { Vector.new(_y, _x) } // Perpendicular
toString { "(%(_x), %(_y))" }
}
var v = Vector.new(3, 4)
System.print((-v).toString) // (-3, -4)</code></pre>
<h3>Subscript Operators</h3>
<pre><code>class Grid {
construct new(width, height) {
_width = width
_height = height
_cells = List.filled(width * height, 0)
}
[x, y] { _cells[y * _width + x] }
[x, y]=(value) { _cells[y * _width + x] = value }
}
var grid = Grid.new(10, 10)
grid[5, 3] = 42
System.print(grid[5, 3]) // 42</code></pre>
<h2>Calling Methods</h2>
<h3>With Parentheses</h3>
<pre><code>object.method()
object.method(arg1)
object.method(arg1, arg2)</code></pre>
<h3>Without Parentheses (Getters)</h3>
<pre><code>object.property
object.count
string.bytes</code></pre>
<h3>With Block Argument</h3>
<pre><code>list.map { |x| x * 2 }
list.where { |x| x > 5 }
list.each { |x| System.print(x) }</code></pre>
<h3>Chaining</h3>
<pre><code>var result = list
.where { |x| x > 0 }
.map { |x| x * 2 }
.toList</code></pre>
<h2>Return Values</h2>
<p>Methods return the last expression or use <code>return</code>:</p>
<pre><code>class Example {
implicit() {
42 // Implicit return
}
explicit() {
return 42 // Explicit return
}
early(x) {
if (x &lt; 0) return -1
if (x > 0) return 1
return 0
}
}</code></pre>
<p>Methods without a return statement return <code>null</code>.</p>
<h2>Method References</h2>
<p>You cannot directly reference a method as a value. Use a block wrapper:</p>
<pre><code>class Printer {
static print(value) {
System.print(value)
}
}
var fn = Fn.new { |x| Printer.print(x) }
fn.call("Hello") // Hello</code></pre>
</article>
<footer class="page-footer">
<a href="classes.html" class="prev">Classes</a>
<a href="control-flow.html" class="next">Control Flow</a>
</footer>
</main>
</div>
<script src="../js/main.js"></script>
</body>
</html>