boxlang-language-fundamentals について
boxlang-language-fundamentalsは、BoxLangのコードを書く開発者やエージェント向けの基礎リファレンスです。JVM言語としての構文、型、スコープ、よくある注意点をコード例とともに解説しています。
主な機能
- 01BoxLangのファイル形式と用途
- 02変数、スコープ、動的型付け
- 03制御フローと例外処理
- 04配列のインデックスとJava連携
- 05関数構文と組み込み関数
活用シーン
- 01BoxLang構文の参照
- 02BoxLangスクリプトやクラスの作成
- 03配列やスコープの挙動確認
- 04Java呼び出しやセミコロンの誤り回避
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ ortus-boxlang/ skills --skill boxlang-language-fundamentalsインストール後、Claude Code で/boxlang-language-fundamentalsを入力して読み込まれたか確認します。
詳細
BoxLang 言語の基礎
BoxLang は、開発者と AI エージェントが協力してアプリケーションを構築、モダナイズ、実行するための、AI ネイティブなソフトウェア生産性プラットフォームです。
概要
BoxLang は、Java、CFML、Python、Ruby、Go、PHP の影響を受けた、モダンで動的な JVM 言語(JRE 21 以降)です。Java バイトコードにコンパイルされ、より表現力豊かで簡潔な構文を備えた、完全な Java 相互運用性を提供します。
ファイルの種類
| 拡張子 | 用途 |
|---|---|
.bx | クラスファイル(コンポーネント、サービス、モデル) |
.bxs | スクリプトファイル(スタンドアロンスクリプト、CLI) |
.bxm | マークアップ/テンプレートファイル(HTML 出力、ビュー) |
変数とスコープ
BoxLang は動的型付けを採用しており、型は実行時に推論されます。型を明示的に注釈する必要はありませんが、指定することもできます。
// Variable declaration (var keyword in functions)
var name = "BoxLang"
var count = 42
var price = 9.99
var active = true
// Null
var nothing = null
スコープチェーン(関数内での解決順序)
local— 関数内でvarを使って宣言された変数arguments— 関数のパラメーターvariables— コンポーネント/クラスのプライベートスコープthis— コンポーネント/クラスのパブリックスコープ- 名前付きスコープ:
url、form、session、application、request、cgi、server
// Explicit scope reference
variables.counter = 0
this.publicValue = "visible"
local.tempResult = compute()
演算子
// Arithmetic
a + b a - b a * b a / b a % b a ^ b a \ b // integer divide
// Comparison
a == b a != b a > b a < b a >= b a <= b
a === b a !== b // strict (type + value)
// Logical
a && b a || b !a
a and b a or b not a // word operators
// String concatenation
a & b
// Safe-navigation (null-safe member access)
user?.address?.city // returns null instead of throwing
// Inclusive range (v1.12+)
1..5 // produces [1, 2, 3, 4, 5] — both ends included
// Ternary
result = condition ? trueValue : falseValue
// Elvis (null coalescing)
result = value ?: "default"
制御フロー
// if / else if / else
if ( age >= 18 ) {
writeOutput( "adult" )
} else if ( age >= 13 ) {
writeOutput( "teen" )
} else {
writeOutput( "child" )
}
// switch
switch ( status ) {
case "active":
doActive()
break
case "pending":
case "review":
doPending()
break
default:
doDefault()
}
// for (index)
for ( var i = 1; i <= 10; i++ ) {
writeOutput( i )
}
// for-in (collection)
for ( var item in myArray ) {
writeOutput( item )
}
// for-in with destructuring (v1.12+)
for ( var [key, value] in myStruct ) {
writeOutput( "#key# = #value#" )
}
// while
while ( queue.len() > 0 ) {
process( queue.dequeue() )
}
// do-while
do {
attempt = tryConnect()
} while ( !attempt.success && retries++ < 3 )
例外処理
try {
result = riskyOperation()
} catch ( "CustomException" e ) {
handleCustom( e )
} catch ( any e ) {
// e.message, e.detail, e.stackTrace, e.type
logError( e.message )
} finally {
cleanup()
}
// Throwing exceptions
throw( message="Something went wrong", type="MyApp.ValidationError", detail="Field X is required" )
// Or as an object
throw new MyException( "Bad input" )
文字列
// Double-quoted: interpolation enabled
var greeting = "Hello, #name#!"
var multi = "Line one
Line two"
// Single-quoted: literal (no interpolation)
var literal = 'Hello, #name#' // outputs literally: Hello, #name#
// Common string functions
len( str )
trim( str )
uCase( str ) / lCase( str )
left( str, n ) / right( str, n ) / mid( str, start, n )
replace( str, search, replacement )
reFind( pattern, str )
listToArray( str, delimiter )
str.contains( "foo" ) // member function syntax
配列
重要:BoxLang の配列は 1 始まりです(Java のように 0 始まりではありません)。
最初の要素のインデックスは常に 1 です。
var fruits = [ "apple", "banana", "cherry" ]
// Access by index — starts at 1
fruits[ 1 ] // "apple" ✅
fruits[ 0 ] // null / out-of-bounds ❌ WRONG
// Preferred: use named accessors instead of numeric index
fruits.first() // "apple" — first element
fruits.last() // "cherry" — last element
// Common array operations
fruits.len() // 3
fruits.append( "date" ) // adds to end
fruits.prepend( "avocado" ) // adds to front
fruits.isEmpty() // false
fruits.contains( "banana" ) // true
fruits.find( "cherry" ) // 3 (1-based index, 0 if not found)
fruits.each( (f) -> println(f) )
fruits.map( (f) -> uCase(f) )
fruits.filter( (f) -> f.startsWith("a") )
fruits.reduce( (acc, f) -> acc & "," & f, "" )
// Inline array literal
var nums = [ 1, 2, 3, 4, 5 ]
// Spread (v1.12+)
var more = [ ...nums, 6, 7 ]
可変長引数/Java の位置引数呼び出しでは配列を使用する必要があります
Object... args(可変長引数)を受け取る Java メソッドを呼び出す場合は、BoxLang の配列を必ず渡してください。値を 1 つだけそのまま渡しても機能しません。
// WRONG — bare value
storage.query( "SELECT * FROM users WHERE id = ?", userId )
// CORRECT — wrapped in an array
storage.query( "SELECT * FROM users WHERE id = ?", [userId] )
// Multiple params
storage.query( "SELECT * FROM users WHERE role = ? AND active = ?", [role, active] )
セミコロン
文末のセミコロンは省略可能で、冗長と見なされます。 変数宣言、関数呼び出し、return 文、制御フローブロックには追加しないでください。
// BAD — noisy semicolons
var name = "BoxLang";
var total = items.len();
return total;
// GOOD — clean, no semicolons
var name = "BoxLang"
var total = items.len()
return total
セミコロンが必要(または慣例的に使われる)場所は 2 つあります。
-
自己終了コンポーネントタグ — タグの呼び出しを終了します。
bx:header name="Content-Type" value="application/json"; bx:location url="/login" addToken=false; bx:abort; -
クラス内のプロパティ宣言:
class MyComponent { bx:property name="title" type="string" default=""; bx:property name="count" type="numeric" default=0; }
型システム
BoxLang は動的型付けですが、任意で型を強制できます。
// Type annotations (optional)
string function greet( required string name ) {
return "Hello, #name#!"
}
// Auto-casting
var num = "42" + 0 // 42 (string auto-cast to number)
var bool = "true" // truthy
var date = "2024-01-15" // auto-cast to date in date functions
// Type checking
isNumeric( val )
isDate( val )
isArray( val )
isStruct( val )
isNull( val )
getMetaData( obj ).name // introspect type
モダンな機能(v1.12 以降)
// Array destructuring
var [first, second, ...rest] = myArray
var [a, b] = [1, 2]
// Struct destructuring
var { name, age } = person
var { name: fullName, age: years } = person // rename
// Spread in function calls
var args = [1, 2, 3]
sum( ...args )
// Spread in array/struct literals
var combined = [...arr1, ...arr2]
var merged = {...struct1, ...struct2}
// For-loop destructuring
for ( var [key, val] in myStruct ) { ... }
for ( var [index, item] in myArray ) { ... }
コメント
// Single-line comment
/* Multi-line
comment */
/**
* Doc-comment (used for annotation metadata)
* @param name The user's name
* @return Greeting string
*/
組み込み関数(BIF)
BIF はインポートせずにグローバルに使用できます。直接呼び出すか、メンバー関数として呼び出してください。
// Function-style
len( myArray )
arrayAppend( myArray, item )
structKeyExists( myStruct, "key" )
// Member-function style (preferred)
myArray.len()
myArray.append( item )
myStruct.keyExists( "key" )
// List all available BIFs
writeDump( getFunctionList() )
出力
writeOutput( "Hello" ) // write to output buffer
println( "Hello" ) // write + newline (scripts)
dump( var=myVar ) // debug dump
writeDump( myVar ) // alias for dump
abort // stop execution
モダンな関数構文
function キーワードを使わないメソッド宣言
class 本文内では、function キーワードを省略できます。BoxLang では、コロンを使った任意の戻り値型注釈を備えた簡潔な宣言スタイルがサポートされています。
class MathService {
// Concise declaration — no "function" keyword
add( numeric a, numeric b ) {
return a + b
}
// With return-type annotation (colon syntax)
multiply( required numeric a, required numeric b ):numeric {
return a * b
}
// With default parameter value and return type
power( required numeric base, numeric exponent = 2 ):numeric {
return base ^ exponent
}
// Void-like — no return type declared
logOperation( required string operation ) {
writeLog( "Operation: #operation#" )
}
}
使用できる戻り値の型:string、numeric、boolean、array、struct、query、date、void、any、または完全修飾クラス名。
従来の function キーワード(引き続き有効)
class Service {
function calculate( required numeric value ):numeric {
return value * 2
}
}
どちらのスタイルも同等です。クラス内では簡潔なスタイルを推奨します。スタンドアロンのスクリプトレベルの関数やクロージャーでは、function キーワードを使用してください。
クイックリファレンス:よくある落とし穴
| 落とし穴 | 誤り | 正しい |
|---|---|---|
| 配列のインデックス指定 | arr[ 0 ] | arr[ 1 ] または arr.first() |
| 末尾のセミコロン | var x = 1; | var x = 1 |
| 可変長引数の呼び出し | query( sql, singleVal ) | query( sql, [singleVal] ) |
| BoxLang での CFML 関数 | cfheader( ... ) | bx:header name=... value=...; |
Java スタイルの // は不要 | n/a | // と /* */ の両方が使用可能 |