Lens4D는 불변 데이터 구조를 위한 조합 가능하고 재사용 가능한 타입 안전한 렌즈를 생성할 수 있게 해주는 Dart 패키지입니다. 변경 없이 중첩된 데이터에 접근하고 업데이트하기 위한 함수형 프로그래밍 방식을 제공하여 코드의 명확성과 유지보수성을 향상시킵니다. 렌즈는 개발자가 복잡한 데이터 모델의 특정 부분에 집중할 수 있도록 하여 업데이트가 예측 가능하고 안전하게 만듭니다. 대규모 애플리케이션에서 상태 관리에 이상적이며, Lens4D는 웹, 모바일, 데스크톱을 포함한 모든 주요 플랫폼을 지원합니다.
사용 사례
불변 상태 업데이트
중첩된 데이터 조작
기능적 상태 관리
반응형 UI 개발
형 안전한 데이터 접근
데이터 변환에서의 코드 재사용
주요 기능
형 안전한 렌즈 생성
조합 가능한 렌즈
불변 데이터 업데이트
중첩 구조 지원
함수형 프로그래밍 패러다임
크로스플랫폼 호환성
적합한 대상
함수형 프로그래밍을 사용하는 개발자
대규모 앱에서의 상태 관리
타입 안정성을 우선시하는 팀
복잡한 중첩 데이터를 가진 애플리케이션
다양한 플랫폼을 대상으로 하는 프론트엔드 개발자
고려 사항
함수형 프로그래밍에 대한 이해가 필요합니다
초보자를 위한 학습 곡선
불변 데이터 패턴에 가장 적합
간단한 사용 사례에서 오버헤드가 추가될 수 있습니다
주류 패키지에 비해 문서가 제한적
원본 README
연결된 소스 저장소의 README 원문 스냅샷입니다. 최신 내용은 저장소에서 확인하세요.
lens4d
A functional lens library for Dart, enabling type-safe, composable data access and modification.
Overview
Lenses are a functional programming pattern that provide a clean, type-safe way to focus on, extract from, and modify deeply nested data structures. Originally from Haskell and popularized in languages like Scala and Kotlin, lenses solve the problem of working with immutable data in an elegant, composable way.
This library is inspired by and adapted from the lens system in http4k Kotlin library, bringing the power of functional lenses to Dart.
Why Lenses?
Working with immutable data often leads to verbose, error-prone code:
// Without lenses - verbose and fragilefinal newUri = uri.replace(
queryParameters: {
...uri.queryParameters,
'search': 'flutter',
'limit': '20',
}
);
With lenses, the same operation becomes clean and composable:
// With lenses - clean and type-safefinal newUri = uri.havingAll([
Query.required('search').of('flutter'),
Query.integer().required('limit').of(20),
]);
Features
✅ Type-safe data access - Extract and modify values with compile-time type safety
✅ Functional composition - Chain operations with having() and havingAll()
✅ Bidirectional lenses - Both read from and write to data structures
✅ Type conversions - Built-in conversions for integers, booleans, dates, and more
✅ Error handling - Comprehensive failure handling with detailed error information
✅ Zero dependencies - Pure Dart implementation
Quick Start
Installation
Add lens4d to your pubspec.yaml:
dependencies:lens4d:^1.0.0
Basic Usage
Here's a practical example working with URI query parameters:
import'package:lens4d/lens4d.dart';
/// Define a Query lens for Uri objectsfinalQuery = BiDiLensSpec<Uri, String>(
'query',
constStringParam(),
LensGet<Uri, String>((name, uri) {
final value = uri.queryParameters[name];
return value != null ? [value] : [];
}),
LensSet<Uri, String>((name, values, uri) {
final newParams = Map<String, String>.from(uri.queryParameters);
if (values.isEmpty) {
newParams.remove(name);
} else {
newParams[name] = values.first;
}
return uri.replace(queryParameters: newParams);
}),
);
voidmain() {
final uri = Uri.parse('https://api.example.com/search?q=dart&limit=10');
// Extract values with type safetyfinal searchTerm = Query.required('q')(uri); // 'dart'final limit = Query.integer().required('limit')(uri); // 10 (as int)final page = Query.integer().optional('page')(uri); // null// Single modificationfinal newUri = uri.having(Query.required('q').of('flutter'));
// Multiple modificationsfinal complexUri = uri.havingAll([
Query.required('search').of('dart programming'),
Query.integer().required('limit').of(50),
Query.boolean().required('debug').of(true),
]);
// Error handlingtry {
Query.required('missing')(uri);
} onLensFailurecatch (e) {
print('Parameter not found: ${e.failures.first}');
}
}
Type Conversions
Lenses support automatic type conversions, which are extensible via extension methods:
The having() and havingAll() extension methods enable clean functional composition:
// Chain single modificationsfinal result = data
.having(someLens.of(value1))
.having(anotherLens.of(value2));
// Apply multiple modifications at oncefinal result = data.havingAll([
lens1.of(value1),
lens2.of(value2),
lens3.of(value3),
]);
API Overview
BiDiLensSpec<IN, OUT> - Bidirectional lens specification for extraction and injection
LensSpec<IN, OUT> - Unidirectional lens for extraction only