πΉ Conditional Logic in TuskLang - Go Guide
Conditional Logic in TuskLang - Go Guide
π― The Power of Dynamic Configuration
In TuskLang, conditional logic isn't just about if/elseβit's about making your configuration alive and responsive. We don't bow to any king, especially not static configuration files. TuskLang gives you the power to make decisions at configuration time, not just runtime.
π Table of Contents
- Understanding Conditional Logic - Basic Conditional Syntax - Go Integration - Advanced Conditional Patterns - Environment-Based Logic - Performance Considerations - Real-World Examples - Best Practicesπ Understanding Conditional Logic
TuskLang's conditional logic operates at configuration time, allowing dynamic decision-making:
// TuskLang configuration with conditionals
[environment_config]
debug_mode: @if(@env("DEBUG"), true, false)
log_level: @if(@env("PRODUCTION"), "error", "debug")
cache_enabled: @if(@env("CACHE"), true, false)[feature_flags]
beta_features: @if(@env("BETA"), true, false)
experimental: @if(@env("EXPERIMENTAL"), true, false)
// Go integration
type EnvironmentConfig struct {
DebugMode bool tsk:"debug_mode"
LogLevel string tsk:"log_level"
CacheEnabled bool tsk:"cache_enabled"
}type FeatureFlags struct {
BetaFeatures bool tsk:"beta_features"
Experimental bool tsk:"experimental"
}
π¨ Basic Conditional Syntax
Simple If Statements
// TuskLang - Basic conditional syntax
[basic_conditionals]
value1: @if(condition, true_value, false_value)
value2: @if(@env("DEBUG"), "debug", "production")
value3: @if(@env("FEATURE_FLAG"), "enabled", "disabled")
// Go - Handling basic conditionals
type BasicConditionals struct {
Value1 string tsk:"value1"
Value2 string tsk:"value2"
Value3 string tsk:"value3"
}func (b *BasicConditionals) IsDebugMode() bool {
return b.Value2 == "debug"
}
func (b *BasicConditionals) IsFeatureEnabled() bool {
return b.Value3 == "enabled"
}
Nested Conditionals
// TuskLang - Nested conditional logic
[nested_conditionals]
log_level: @if(@env("PRODUCTION"),
"error",
@if(@env("STAGING"), "warn", "debug")
)cache_strategy: @if(@env("MEMORY_LIMIT") > 1024,
"redis",
@if(@env("DISK_SPACE") > 1000, "file", "memory")
)
// Go - Handling nested conditionals
type NestedConditionals struct {
LogLevel string tsk:"log_level"
CacheStrategy string tsk:"cache_strategy"
}func (n *NestedConditionals) GetLogLevel() string {
return n.LogLevel
}
func (n *NestedConditionals) GetCacheStrategy() string {
return n.CacheStrategy
}
func (n *NestedConditionals) IsProduction() bool {
return n.LogLevel == "error"
}
func (n *NestedConditionals) IsStaging() bool {
return n.LogLevel == "warn"
}
func (n *NestedConditionals) IsDevelopment() bool {
return n.LogLevel == "debug"
}
Complex Conditional Logic
// TuskLang - Complex conditional expressions
[complex_conditionals]
database_url: @if(@env("DATABASE_URL"),
@env("DATABASE_URL"),
@if(@env("DB_HOST") && @env("DB_NAME"),
@concat("postgresql://", @env("DB_USER"), ":", @env("DB_PASS"), "@", @env("DB_HOST"), ":", @env("DB_PORT"), "/", @env("DB_NAME")),
"sqlite://local.db"
)
)api_timeout: @if(@env("API_TIMEOUT"),
@env("API_TIMEOUT"),
@if(@env("PRODUCTION"), 30, 60)
)
// Go - Handling complex conditionals
type ComplexConditionals struct {
DatabaseURL string tsk:"database_url"
APITimeout int tsk:"api_timeout"
}func (c *ComplexConditionals) GetDatabaseURL() string {
return c.DatabaseURL
}
func (c *ComplexConditionals) GetAPITimeout() time.Duration {
return time.Duration(c.APITimeout) * time.Second
}
func (c *ComplexConditionals) IsUsingExternalDatabase() bool {
return strings.Contains(c.DatabaseURL, "postgresql://")
}
func (c *ComplexConditionals) IsUsingLocalDatabase() bool {
return strings.Contains(c.DatabaseURL, "sqlite://")
}
π§ Go Integration
Conditional Configuration Loading
// Go - Dynamic configuration loading based on conditions
type ConditionalLoader struct {
Config *AppConfig
}func (c *ConditionalLoader) LoadConfig() error {
// Determine environment
env := os.Getenv("ENVIRONMENT")
if env == "" {
env = "development"
}
// Load appropriate config file
configFile := fmt.Sprintf("config.%s.tsk", env)
config := &AppConfig{}
err := tusk.ParseFile(configFile, config)
if err != nil {
return fmt.Errorf("failed to load config: %w", err)
}
c.Config = config
return nil
}
func (c *ConditionalLoader) ValidateConfig() error {
if c.Config == nil {
return errors.New("configuration not loaded")
}
// Environment-specific validation
if c.Config.Environment == "production" {
if c.Config.DebugMode {
return errors.New("debug mode should be disabled in production")
}
if c.Config.LogLevel == "debug" {
return errors.New("debug logging should be disabled in production")
}
}
return nil
}
Conditional Feature Flags
// Go - Feature flag implementation
type FeatureFlags struct {
BetaFeatures bool tsk:"beta_features"
Experimental bool tsk:"experimental"
DarkMode bool tsk:"dark_mode"
Analytics bool tsk:"analytics"
Notifications bool tsk:"notifications"
}func (f *FeatureFlags) IsFeatureEnabled(feature string) bool {
switch feature {
case "beta":
return f.BetaFeatures
case "experimental":
return f.Experimental
case "dark_mode":
return f.DarkMode
case "analytics":
return f.Analytics
case "notifications":
return f.Notifications
default:
return false
}
}
func (f *FeatureFlags) GetEnabledFeatures() []string {
var features []string
if f.BetaFeatures {
features = append(features, "beta")
}
if f.Experimental {
features = append(features, "experimental")
}
if f.DarkMode {
features = append(features, "dark_mode")
}
if f.Analytics {
features = append(features, "analytics")
}
if f.Notifications {
features = append(features, "notifications")
}
return features
}
Conditional Validation
// Go - Conditional validation rules
type ConditionalValidation struct {
Environment string tsk:"environment"
DebugMode bool tsk:"debug_mode"
LogLevel string tsk:"log_level"
APIKey string tsk:"api_key"
DatabaseURL string tsk:"database_url"
}func (c *ConditionalValidation) Validate() error {
var errors []error
// Environment-specific validation
if c.Environment == "production" {
if c.DebugMode {
errors = append(errors, errors.New("debug mode cannot be enabled in production"))
}
if c.LogLevel == "debug" {
errors = append(errors, errors.New("debug logging cannot be enabled in production"))
}
if c.APIKey == "" {
errors = append(errors, errors.New("API key is required in production"))
}
if !strings.Contains(c.DatabaseURL, "postgresql://") {
errors = append(errors, errors.New("production must use PostgreSQL"))
}
}
// Development-specific validation
if c.Environment == "development" {
if c.APIKey != "" {
errors = append(errors, errors.New("API key should not be set in development"))
}
}
if len(errors) > 0 {
return fmt.Errorf("validation failed: %v", errors)
}
return nil
}
π Advanced Conditional Patterns
Switch-Like Conditionals
// TuskLang - Switch-like conditional logic
[switch_conditionals]
environment: @env("ENVIRONMENT")log_level: @switch(@env("ENVIRONMENT"),
"production", "error",
"staging", "warn",
"development", "debug",
"debug"
)
database_type: @switch(@env("DB_TYPE"),
"postgresql", "postgresql://localhost:5432/app",
"mysql", "mysql://localhost:3306/app",
"sqlite", "sqlite://local.db",
"sqlite://local.db"
)
// Go - Handling switch-like conditionals
type SwitchConditionals struct {
Environment string tsk:"environment"
LogLevel string tsk:"log_level"
DatabaseType string tsk:"database_type"
}func (s *SwitchConditionals) GetLogLevel() string {
return s.LogLevel
}
func (s *SwitchConditionals) GetDatabaseType() string {
return s.DatabaseType
}
func (s *SwitchConditionals) IsProduction() bool {
return s.Environment == "production"
}
func (s *SwitchConditionals) IsStaging() bool {
return s.Environment == "staging"
}
func (s *SwitchConditionals) IsDevelopment() bool {
return s.Environment == "development"
}
Conditional Arrays and Maps
// TuskLang - Conditional arrays and maps
[conditional_arrays]
features: @if(@env("BETA"),
["feature1", "feature2", "feature3"],
["feature1"]
)plugins: @if(@env("EXPERIMENTAL"),
{
"plugin1": "enabled",
"plugin2": "enabled",
"plugin3": "enabled"
},
{
"plugin1": "enabled"
}
)
// Go - Handling conditional arrays and maps
type ConditionalArrays struct {
Features []string tsk:"features"
Plugins map[string]string tsk:"plugins"
}func (c *ConditionalArrays) HasFeature(feature string) bool {
for _, f := range c.Features {
if f == feature {
return true
}
}
return false
}
func (c *ConditionalArrays) IsPluginEnabled(plugin string) bool {
status, exists := c.Plugins[plugin]
return exists && status == "enabled"
}
func (c *ConditionalArrays) GetEnabledPlugins() []string {
var enabled []string
for plugin, status := range c.Plugins {
if status == "enabled" {
enabled = append(enabled, plugin)
}
}
return enabled
}
Conditional Functions
// TuskLang - Conditional function execution
[conditional_functions]
process_data: @if(@env("ENABLE_PROCESSING"),
"""function process(data) { return data.map(x => x * 2); }""",
"""function process(data) { return data; }"""
)validate_input: @if(@env("STRICT_VALIDATION"),
"""function validate(input) { return input.length > 0 && input.length < 100; }""",
"""function validate(input) { return true; }"""
)
// Go - Handling conditional functions
type ConditionalFunctions struct {
ProcessData string tsk:"process_data"
ValidateInput string tsk:"validate_input"
}func (c *ConditionalFunctions) ExecuteProcessData(data []int) ([]int, error) {
// Execute the conditional function
result, err := tusk.ExecuteFunction(c.ProcessData, "process", data)
if err != nil {
return nil, fmt.Errorf("failed to execute process function: %w", err)
}
// Convert result to []int
if processed, ok := result.([]int); ok {
return processed, nil
}
return nil, errors.New("invalid result type from process function")
}
func (c *ConditionalFunctions) ExecuteValidateInput(input string) (bool, error) {
// Execute the conditional function
result, err := tusk.ExecuteFunction(c.ValidateInput, "validate", input)
if err != nil {
return false, fmt.Errorf("failed to execute validate function: %w", err)
}
// Convert result to bool
if valid, ok := result.(bool); ok {
return valid, nil
}
return false, errors.New("invalid result type from validate function")
}
π Environment-Based Logic
Environment-Specific Configuration
// TuskLang - Environment-specific configuration
[environment_specific]
database_url: @if(@env("ENVIRONMENT") == "production",
@env("DATABASE_URL"),
@if(@env("ENVIRONMENT") == "staging",
"postgresql://staging:5432/app",
"sqlite://local.db"
)
)api_endpoint: @if(@env("ENVIRONMENT") == "production",
"https://api.production.com",
@if(@env("ENVIRONMENT") == "staging",
"https://api.staging.com",
"http://localhost:3000"
)
)
log_level: @if(@env("ENVIRONMENT") == "production",
"error",
@if(@env("ENVIRONMENT") == "staging",
"warn",
"debug"
)
)
// Go - Environment-specific configuration handling
type EnvironmentSpecific struct {
DatabaseURL string tsk:"database_url"
APIEndpoint string tsk:"api_endpoint"
LogLevel string tsk:"log_level"
}func (e *EnvironmentSpecific) GetEnvironment() string {
env := os.Getenv("ENVIRONMENT")
if env == "" {
env = "development"
}
return env
}
func (e *EnvironmentSpecific) IsProduction() bool {
return e.GetEnvironment() == "production"
}
func (e *EnvironmentSpecific) IsStaging() bool {
return e.GetEnvironment() == "staging"
}
func (e *EnvironmentSpecific) IsDevelopment() bool {
return e.GetEnvironment() == "development"
}
func (e *EnvironmentSpecific) GetDatabaseURL() string {
return e.DatabaseURL
}
func (e *EnvironmentSpecific) GetAPIEndpoint() string {
return e.APIEndpoint
}
func (e *EnvironmentSpecific) GetLogLevel() string {
return e.LogLevel
}
Feature Toggle Logic
// TuskLang - Feature toggle logic
[feature_toggles]
dark_mode: @if(@env("DARK_MODE") == "true", true, false)
analytics: @if(@env("ANALYTICS") == "true", true, false)
notifications: @if(@env("NOTIFICATIONS") == "true", true, false)
beta_features: @if(@env("BETA_FEATURES") == "true", true, false)
experimental: @if(@env("EXPERIMENTAL") == "true", true, false)
// Go - Feature toggle handling
type FeatureToggles struct {
DarkMode bool tsk:"dark_mode"
Analytics bool tsk:"analytics"
Notifications bool tsk:"notifications"
BetaFeatures bool tsk:"beta_features"
Experimental bool tsk:"experimental"
}func (f *FeatureToggles) IsFeatureEnabled(feature string) bool {
switch feature {
case "dark_mode":
return f.DarkMode
case "analytics":
return f.Analytics
case "notifications":
return f.Notifications
case "beta_features":
return f.BetaFeatures
case "experimental":
return f.Experimental
default:
return false
}
}
func (f *FeatureToggles) GetEnabledFeatures() []string {
var features []string
if f.DarkMode {
features = append(features, "dark_mode")
}
if f.Analytics {
features = append(features, "analytics")
}
if f.Notifications {
features = append(features, "notifications")
}
if f.BetaFeatures {
features = append(features, "beta_features")
}
if f.Experimental {
features = append(features, "experimental")
}
return features
}
func (f *FeatureToggles) ValidateToggles() error {
// Validate toggle combinations
if f.BetaFeatures && !f.Experimental {
return errors.New("beta features require experimental mode")
}
if f.Analytics && f.Experimental {
return errors.New("analytics should not be enabled with experimental features")
}
return nil
}
β‘ Performance Considerations
Conditional Evaluation Optimization
// Go - Optimized conditional evaluation
type OptimizedConditionals struct {
Environment string tsk:"environment"
DebugMode bool tsk:"debug_mode"
LogLevel string tsk:"log_level"
}func (o *OptimizedConditionals) GetLogLevel() string {
// Cache the result to avoid repeated string comparisons
if o.LogLevel != "" {
return o.LogLevel
}
// Fallback logic
if o.Environment == "production" {
return "error"
} else if o.Environment == "staging" {
return "warn"
}
return "debug"
}
func (o *OptimizedConditionals) ShouldLog(level string) bool {
logLevels := map[string]int{
"debug": 0,
"info": 1,
"warn": 2,
"error": 3,
}
currentLevel := logLevels[o.GetLogLevel()]
messageLevel := logLevels[level]
return messageLevel >= currentLevel
}
Lazy Evaluation
// Go - Lazy evaluation of conditional logic
type LazyConditionals struct {
Config *AppConfig
}func (l *LazyConditionals) GetExpensiveValue() (string, error) {
// Only compute expensive value when needed
if l.Config.Environment == "production" {
return l.computeProductionValue()
} else if l.Config.Environment == "staging" {
return l.computeStagingValue()
}
return l.computeDevelopmentValue()
}
func (l *LazyConditionals) computeProductionValue() (string, error) {
// Expensive computation for production
time.Sleep(100 * time.Millisecond) // Simulate expensive operation
return "production_value", nil
}
func (l *LazyConditionals) computeStagingValue() (string, error) {
// Moderate computation for staging
time.Sleep(50 * time.Millisecond) // Simulate moderate operation
return "staging_value", nil
}
func (l *LazyConditionals) computeDevelopmentValue() (string, error) {
// Simple computation for development
return "development_value", nil
}
π Real-World Examples
Multi-Environment Application Configuration
// TuskLang - Multi-environment configuration
[app_config]
environment: @env("ENVIRONMENT")database: @if(@env("ENVIRONMENT") == "production",
{
"host": @env("DB_HOST"),
"port": @env("DB_PORT"),
"name": @env("DB_NAME"),
"user": @env("DB_USER"),
"pass": @env("DB_PASS"),
"ssl": true
},
@if(@env("ENVIRONMENT") == "staging",
{
"host": "staging-db.example.com",
"port": 5432,
"name": "app_staging",
"user": "staging_user",
"pass": "staging_pass",
"ssl": true
},
{
"host": "localhost",
"port": 5432,
"name": "app_dev",
"user": "dev_user",
"pass": "dev_pass",
"ssl": false
}
)
)
api: @if(@env("ENVIRONMENT") == "production",
{
"base_url": "https://api.production.com",
"timeout": 30,
"retries": 3,
"rate_limit": 1000
},
@if(@env("ENVIRONMENT") == "staging",
{
"base_url": "https://api.staging.com",
"timeout": 60,
"retries": 5,
"rate_limit": 100
},
{
"base_url": "http://localhost:3000",
"timeout": 120,
"retries": 10,
"rate_limit": 10
}
)
)
// Go - Multi-environment configuration handling
type DatabaseConfig struct {
Host string tsk:"host"
Port int tsk:"port"
Name string tsk:"name"
User string tsk:"user"
Pass string tsk:"pass"
SSL bool tsk:"ssl"
}type APIConfig struct {
BaseURL string tsk:"base_url"
Timeout int tsk:"timeout"
Retries int tsk:"retries"
RateLimit int tsk:"rate_limit"
}
type AppConfig struct {
Environment string tsk:"environment"
Database DatabaseConfig tsk:"database"
API APIConfig tsk:"api"
}
func (a *AppConfig) GetDatabaseURL() string {
sslMode := "disable"
if a.Database.SSL {
sslMode = "require"
}
return fmt.Sprintf(
"postgresql://%s:%s@%s:%d/%s?sslmode=%s",
a.Database.User,
a.Database.Pass,
a.Database.Host,
a.Database.Port,
a.Database.Name,
sslMode,
)
}
func (a *AppConfig) GetAPITimeout() time.Duration {
return time.Duration(a.API.Timeout) * time.Second
}
func (a *AppConfig) IsProduction() bool {
return a.Environment == "production"
}
func (a *AppConfig) IsStaging() bool {
return a.Environment == "staging"
}
func (a *AppConfig) IsDevelopment() bool {
return a.Environment == "development"
}
Feature Flag Management System
// TuskLang - Feature flag management
[feature_flags]
environment: @env("ENVIRONMENT")flags: @if(@env("ENVIRONMENT") == "production",
{
"dark_mode": false,
"analytics": true,
"notifications": true,
"beta_features": false,
"experimental": false,
"chat": true,
"video": true,
"ai_assistant": false
},
@if(@env("ENVIRONMENT") == "staging",
{
"dark_mode": true,
"analytics": true,
"notifications": true,
"beta_features": true,
"experimental": true,
"chat": true,
"video": true,
"ai_assistant": true
},
{
"dark_mode": true,
"analytics": false,
"notifications": false,
"beta_features": true,
"experimental": true,
"chat": true,
"video": false,
"ai_assistant": true
}
)
)
// Go - Feature flag management system
type FeatureFlags struct {
Environment string tsk:"environment"
Flags map[string]bool tsk:"flags"
}func (f *FeatureFlags) IsFeatureEnabled(feature string) bool {
enabled, exists := f.Flags[feature]
return exists && enabled
}
func (f *FeatureFlags) GetEnabledFeatures() []string {
var enabled []string
for feature, isEnabled := range f.Flags {
if isEnabled {
enabled = append(enabled, feature)
}
}
return enabled
}
func (f *FeatureFlags) GetDisabledFeatures() []string {
var disabled []string
for feature, isEnabled := range f.Flags {
if !isEnabled {
disabled = append(disabled, feature)
}
}
return disabled
}
func (f *FeatureFlags) ValidateFlags() error {
var errors []error
// Production validation
if f.Environment == "production" {
if f.IsFeatureEnabled("experimental") {
errors = append(errors, errors.New("experimental features cannot be enabled in production"))
}
if f.IsFeatureEnabled("beta_features") {
errors = append(errors, errors.New("beta features cannot be enabled in production"))
}
if !f.IsFeatureEnabled("analytics") {
errors = append(errors, errors.New("analytics must be enabled in production"))
}
}
// Development validation
if f.Environment == "development" {
if f.IsFeatureEnabled("analytics") {
errors = append(errors, errors.New("analytics should not be enabled in development"))
}
}
if len(errors) > 0 {
return fmt.Errorf("feature flag validation failed: %v", errors)
}
return nil
}
π― Best Practices
1. Use Clear Conditional Logic
// β
Good - Clear conditional logic
[good_conditionals]
debug_mode: @if(@env("DEBUG") == "true", true, false)
log_level: @if(@env("ENVIRONMENT") == "production", "error", "debug")// β Bad - Unclear conditional logic
[bad_conditionals]
debug_mode: @if(@env("DEBUG"), true, false) // What if DEBUG is "false"?
log_level: @if(@env("ENVIRONMENT"), "error", "debug") // What if ENVIRONMENT is "staging"?
2. Provide Meaningful Defaults
// β
Good - Meaningful defaults
[good_defaults]
api_timeout: @if(@env("API_TIMEOUT"), @env("API_TIMEOUT"), 30)
retry_count: @if(@env("RETRY_COUNT"), @env("RETRY_COUNT"), 3)// β Bad - No defaults
[bad_defaults]
api_timeout: @env("API_TIMEOUT") // Could be empty
retry_count: @env("RETRY_COUNT") // Could be empty
3. Validate Conditional Results
// β
Good - Validate conditional results
func (c *Config) Validate() error {
if c.Environment == "production" && c.DebugMode {
return errors.New("debug mode cannot be enabled in production")
}
if c.Environment == "development" && c.LogLevel == "error" {
return errors.New("development should use debug logging")
}
return nil
}// β Bad - No validation
func (c *Config) Validate() error {
return nil // No validation of conditional logic
}
4. Use Environment-Specific Configuration Files
// β
Good - Environment-specific files
config.production.tsk
config.staging.tsk
config.development.tsk// β Bad - Single file with complex conditionals
config.tsk // Too many conditionals make it hard to read
5. Document Conditional Logic
// β
Good - Documented conditional logic
[documented_conditionals]
Production uses external database, others use local
database_url: @if(@env("ENVIRONMENT") == "production",
@env("DATABASE_URL"), # External database
"sqlite://local.db" # Local database
)Production disables debug features
debug_mode: @if(@env("ENVIRONMENT") == "production",
false, # Disabled in production
true # Enabled in other environments
)// β Bad - Undocumented conditionals
[undocumented_conditionals]
database_url: @if(@env("ENVIRONMENT") == "production", @env("DATABASE_URL"), "sqlite://local.db")
debug_mode: @if(@env("ENVIRONMENT") == "production", false, true)
---
π You've mastered conditional logic in TuskLang with Go!
Conditional logic in TuskLang transforms static configuration into dynamic, responsive systems. With proper conditional handling, you can build applications that adapt to their environment and user preferences.
Next Steps: - Explore 019-functions-go.md for executable configuration - Master 020-imports-go.md for modular configuration - Dive into 021-operators-go.md for advanced operators
Remember: In TuskLang, conditionals aren't just logicβthey're the heartbeat of your configuration. Use them wisely to create responsive, adaptive systems.