Documentation ¶
Overview ¶
Package stackage implements a flexible stack type optimized for use in creating and presenting conditional Boolean statements, abstract mathematical constructs, or simple lists: the possibilities are endless!
Index ¶
- func DefaultConditionLogLevel() int
- func DefaultStackLogLevel() int
- func SetDefaultConditionLogLevel(lvl any)
- func SetDefaultConditionLogger(logger any)
- func SetDefaultStackLogLevel(lvl any)
- func SetDefaultStackLogger(logger any)
- type Auxiliary
- type ComparisonOperator
- type Condition
- func (r Condition) Addr() (addr string)
- func (r Condition) Auxiliary() (aux Auxiliary)
- func (r Condition) CanNest() (can bool)
- func (r Condition) Category() (cat string)
- func (r Condition) Encap(x ...any) Condition
- func (r Condition) Err() (err error)
- func (r Condition) Evaluate(x ...any) (ev any, err error)
- func (r Condition) Expression() (ex any)
- func (r Condition) ID() (id string)
- func (r *Condition) Init() Condition
- func (r Condition) IsEncap() (is bool)
- func (r Condition) IsFIFO() (is bool)
- func (r Condition) IsInit() (is bool)
- func (r Condition) IsNesting() (is bool)
- func (r Condition) IsPadded() (is bool)
- func (r Condition) IsParen() bool
- func (r Condition) IsZero() bool
- func (r Condition) Keyword() (kw string)
- func (r Condition) Len() int
- func (r Condition) LogLevels() (l string)
- func (r Condition) Logger() (l *log.Logger)
- func (r Condition) NoNesting(state ...bool) Condition
- func (r Condition) NoPadding(state ...bool) Condition
- func (r Condition) Operator() (op Operator)
- func (r Condition) Paren(state ...bool) Condition
- func (r Condition) SetAuxiliary(aux ...Auxiliary) Condition
- func (r Condition) SetCategory(cat string) Condition
- func (r Condition) SetErr(err error) Condition
- func (r Condition) SetEvaluator(x Evaluator) Condition
- func (r Condition) SetExpression(ex any) Condition
- func (r Condition) SetID(id string) Condition
- func (r Condition) SetKeyword(kw any) Condition
- func (r Condition) SetLogLevel(l ...any) Condition
- func (r Condition) SetLogger(logger any) Condition
- func (r Condition) SetOperator(op Operator) Condition
- func (r Condition) SetPresentationPolicy(x PresentationPolicy) Condition
- func (r Condition) SetValidityPolicy(x ValidityPolicy) Condition
- func (r Condition) String() (s string)
- func (r Condition) UnsetLogLevel(l ...any) Condition
- func (r Condition) Valid() (err error)
- type Evaluator
- type Interface
- type LogLevel
- type Operator
- type PresentationPolicy
- type PushPolicy
- type Stack
- func (r Stack) Addr() string
- func (r Stack) Auxiliary() (aux Auxiliary)
- func (r Stack) Avail() (avail int)
- func (r Stack) CanMutex() (can bool)
- func (r Stack) CanNest() bool
- func (r Stack) Cap() (c int)
- func (r Stack) CapReached() (cr bool)
- func (r Stack) Category() (cat string)
- func (r Stack) Defrag(max ...int) Stack
- func (r Stack) Delimiter() string
- func (r Stack) Encap(x ...any) Stack
- func (r Stack) Err() (err error)
- func (r Stack) Fold(state ...bool) Stack
- func (r Stack) ForwardIndices(state ...bool) Stack
- func (r Stack) ID() (id string)
- func (r Stack) Index(idx int) (slice any, ok bool)
- func (r Stack) Insert(x any, left int) (ok bool)
- func (r Stack) IsEncap() (is bool)
- func (r Stack) IsFIFO() (is bool)
- func (r Stack) IsInit() (is bool)
- func (r Stack) IsNesting() (is bool)
- func (r Stack) IsPadded() bool
- func (r Stack) IsParen() bool
- func (r Stack) IsReadOnly() bool
- func (r Stack) IsZero() bool
- func (r Stack) Kind() (k string)
- func (r Stack) LeadOnce(state ...bool) Stack
- func (r Stack) Len() (i int)
- func (r Stack) LogLevels() string
- func (r Stack) Logger() (l *log.Logger)
- func (r Stack) Mutex() Stack
- func (r Stack) NegativeIndices(state ...bool) Stack
- func (r Stack) NoNesting(state ...bool) Stack
- func (r Stack) NoPadding(state ...bool) Stack
- func (r Stack) Paren(state ...bool) Stack
- func (r Stack) Pop() (popped any, ok bool)
- func (r Stack) Push(y ...any) Stack
- func (r Stack) ReadOnly(state ...bool) Stack
- func (r Stack) Remove(idx int) (slice any, ok bool)
- func (r Stack) Replace(x any, idx int) bool
- func (r Stack) Reset()
- func (r Stack) Reveal() Stack
- func (r Stack) Reverse() Stack
- func (r Stack) SetAuxiliary(aux ...Auxiliary) Stack
- func (r Stack) SetCategory(cat string) Stack
- func (r Stack) SetDelimiter(x any) Stack
- func (r Stack) SetErr(err error) Stack
- func (r Stack) SetFIFO(fifo bool) Stack
- func (r Stack) SetID(id string) Stack
- func (r Stack) SetLogLevel(l ...any) Stack
- func (r Stack) SetLogger(logger any) Stack
- func (r Stack) SetPresentationPolicy(ppol PresentationPolicy) Stack
- func (r Stack) SetPushPolicy(ppol PushPolicy) Stack
- func (r Stack) SetValidityPolicy(vpol ValidityPolicy) Stack
- func (r Stack) String() (s string)
- func (r Stack) Symbol(c ...any) Stack
- func (r Stack) Transfer(dest Stack) (ok bool)
- func (r Stack) Traverse(indices ...int) (slice any, ok bool)
- func (r Stack) UnsetLogLevel(l ...any) Stack
- func (r Stack) Valid() (err error)
- type ValidityPolicy
Examples ¶
- And (SymbolicAnd)
- Auxiliary.Get
- Auxiliary.Len
- Auxiliary.Set
- Auxiliary.Unset
- Basic
- Basic (SetAsReadOnly)
- Basic (WithCapacity)
- ComparisonOperator.Context
- ComparisonOperator.String
- Cond
- Condition (OneShot)
- Condition (Procedural)
- Condition (TypeAlias)
- Condition.Addr
- Condition.Auxiliary
- Condition.Auxiliary (ByTypeCast)
- Condition.Auxiliary (NoInit)
- Condition.Auxiliary (UserInit)
- Condition.Auxiliary (WithInit)
- Condition.CanNest
- Condition.Category
- Condition.Encap (DoubleQuote)
- Condition.Encap (Tag)
- Condition.Err
- Condition.Evaluate
- Condition.Expression
- Condition.ID
- Condition.Init
- Condition.IsEncap
- Condition.IsFIFO
- Condition.IsInit
- Condition.IsNesting
- Condition.IsPadded
- Condition.IsParen
- Condition.IsZero
- Condition.Keyword
- Condition.Len
- Condition.LogLevels
- Condition.Logger
- Condition.NoNesting
- Condition.NoPadding
- Condition.Operator
- Condition.Paren
- Condition.SetAuxiliary
- Condition.SetCategory
- Condition.SetErr
- Condition.SetErr (Clear)
- Condition.SetEvaluator
- Condition.SetExpression
- Condition.SetID
- Condition.SetID (PointerAddress)
- Condition.SetID (Random)
- Condition.SetKeyword
- Condition.SetLogLevel
- Condition.SetOperator
- Condition.SetPresentationPolicy
- Condition.SetValidityPolicy
- Condition.String
- Condition.UnsetLogLevel
- Condition.Valid
- DefaultConditionLogLevel
- DefaultStackLogLevel
- List
- Or (SymbolicOr)
- SetDefaultConditionLogLevel
- SetDefaultStackLogLevel
- Stack.Addr
- Stack.Auxiliary
- Stack.Auxiliary (ByTypeCast)
- Stack.Auxiliary (NoInit)
- Stack.Auxiliary (UserInit)
- Stack.Auxiliary (WithInit)
- Stack.Category
- Stack.Delimiter
- Stack.ForwardIndices
- Stack.Insert
- Stack.Kind
- Stack.LeadOnce
- Stack.NegativeIndices
- Stack.Pop (FIFO)
- Stack.Pop (LIFO)
- Stack.Reverse
- Stack.SetAuxiliary
- Stack.SetCategory
- Stack.SetDelimiter
- Stack.SetID (PointerAddress)
- Stack.SetID (Random)
- Stack.SetPresentationPolicy
- Stack.SetPushPolicy
- Stack.SetValidityPolicy
- Stack.Transfer
- Stack.Traverse
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func DefaultConditionLogLevel ¶
func DefaultConditionLogLevel() int
Example ¶
fmt.Printf("%d", DefaultConditionLogLevel())
Output: 0
func DefaultStackLogLevel ¶
func DefaultStackLogLevel() int
Example ¶
fmt.Printf("%d", DefaultStackLogLevel())
Output: 0
func SetDefaultConditionLogLevel ¶
func SetDefaultConditionLogLevel(lvl any)
SetDefaultConditionLogLevel sets the instance of LogLevel (lvl) as a LITERAL value, as the verbosity indicator. When set with appropriate level identifiers, this will increase or decrease log verbosity accordingly. This value shall be used for logging verbosity (or lack thereof) for any newly created (and qualified) instances.
Note that the input value(s) are NOT shifted. Users are expected to either sum the values and cast the product as a LogLevel, OR settle for one of the predefined LogLevel constants.
The default is NoLogLevels, which implies a loglevel of zero (0).
Example ¶
// define a custom loglevel cfg SetDefaultConditionLogLevel( LogLevel3 + // 4 UserLogLevel1 + // 64 UserLogLevel7, // 4096 ) custom := DefaultConditionLogLevel() // turn loglevel to none SetDefaultConditionLogLevel(NoLogLevels) off := DefaultConditionLogLevel() fmt.Printf("%d (custom), %d (off)", custom, off)
Output: 4164 (custom), 0 (off)
func SetDefaultConditionLogger ¶
func SetDefaultConditionLogger(logger any)
SetDefaultConditionLogger is a package-level function that will define which logging facility new instances of Condition or equivalent type alias shall be assigned during initialization procedures.
Logging is available but is set to discard all events by default. Note that enabling this will have no effect on instances already created.
An active logging subsystem within any given Condition shall supercede this default package logger.
The following types/values are permitted:
- string: `none`, `off`, `null`, `discard` will turn logging off
- string: `stdout` will set basic STDOUT logging
- string: `stderr` will set basic STDERR logging
- int: 0 will turn logging off
- int: 1 will set basic STDOUT logging
- int: 2 will set basic STDERR logging
- *log.Logger: user-defined *log.Logger instance will be set
Case is not significant in the string matching process.
Logging may also be set for individual Condition instances using the SetLogger method. Similar semantics apply.
func SetDefaultStackLogLevel ¶
func SetDefaultStackLogLevel(lvl any)
SetDefaultStackLogLevel sets the instance of LogLevel (lvl) as a LITERAL value, as the verbosity indicator. When set with appropriate level identifiers, this will increase or decrease log verbosity accordingly. This value shall be used for logging verbosity (or lack thereof) for any newly created (and qualified) instances.
Note that the input value(s) are NOT shifted. Users are expected to either sum the values and cast the product as a LogLevel, OR settle for one of the predefined LogLevel constants.
The default is NoLogLevels, which implies a loglevel of zero (0).
Example ¶
SetDefaultStackLogLevel( LogLevel1 + // 1 LogLevel4 + // 8 UserLogLevel2 + // 128 UserLogLevel5, // 1024 ) custom := DefaultStackLogLevel() // turn loglevel to none SetDefaultStackLogLevel(NoLogLevels) off := DefaultStackLogLevel() fmt.Printf("%d (custom), %d (off)", custom, off)
Output: 1161 (custom), 0 (off)
func SetDefaultStackLogger ¶
func SetDefaultStackLogger(logger any)
SetDefaultStackLogger is a package-level function that will define which logging facility new instances of Stack or equivalent type alias shall be assigned during initialization procedures.
Logging is available but is set to discard all events by default. Note that enabling this will have no effect on instances already created.
An active logging subsystem within any given Stack shall supercede this default package logger.
The following types/values are permitted:
- string: `none`, `off`, `null`, `discard` will turn logging off
- string: `stdout` will set basic STDOUT logging
- string: `stderr` will set basic STDERR logging
- int: 0 will turn logging off
- int: 1 will set basic STDOUT logging
- int: 2 will set basic STDERR logging
- *log.Logger: user-defined *log.Logger instance will be set
Case is not significant in the string matching process.
Logging may also be set for individual Stack instances using the SetLogger method. Similar semantics apply.
Types ¶
type Auxiliary ¶
Auxiliary is a map[string]any type alias extended by this package. It can be created within any Stack instance when [re]initialized using the SetAuxiliary method extended through instances of the Stack type, and can be accessed using the Auxiliary() method in similar fashion.
The Auxiliary type extends four (4) methods: Get, Set, Len and Unset. These are purely for convenience. Given that instances of this type can easily be cast to standard map[string]any by the user, the use of these methods is entirely optional.
The Auxiliary map instance is available to be leveraged in virtually any way deemed appropriate by the user. Its primary purpose is for storage of any instance(s) pertaining to the *administration of the stack*, as opposed to the storage of content normally submitted *into* said stack.
Examples of suitable instance types for storage within the Auxiliary map include, but are certainly not limited to:
- HTTP server listener / mux
- HTTP client, agent
- Graphviz node data
- Go Metrics meters, gauges, etc.
- Redis cache
- bytes.Buffer
- ANTLR parser
- text/template instances
- channels
Which instances are considered suitable for storage within Auxiliary map instances is entirely up to the user. This package shall not impose ANY controls or restrictions regarding the content within this instances of this type, nor its behavior.
func (Auxiliary) Get ¶
Get returns the value associated with key, alongside a presence-indicative Boolean value (ok).
Even if found within the receiver instance, if value is nil, ok shall be explicitly set to false prior to return.
Case is significant in the matching process.
Example ¶
var aux Auxiliary = make(Auxiliary, 0) aux.Set(`value`, 18) val, ok := aux.Get(`value`) if ok { fmt.Printf("%d", val) }
Output: 18
func (Auxiliary) Len ¶
Len returns the integer length of the receiver, defining the number of key/value pairs present.
Example ¶
aux := Auxiliary{ `value`: 18, } fmt.Printf("Len: %d", aux.Len())
Output: Len: 1
func (Auxiliary) Set ¶
Set associates key with value, and assigns to receiver instance. See also the Unset method.
If the receiver is not initialized, a new allocation is made.
Example ¶
var aux Auxiliary = make(Auxiliary, 0) aux.Set(`value`, 18) aux.Set(`color`, `red`) aux.Set(`max`, 200) fmt.Printf("Len: %d", aux.Len())
Output: Len: 3
func (Auxiliary) Unset ¶
Unset removes the key/value pair, identified by key, from the receiver instance, if found. See also the Set method.
This method internally calls the following builtin:
delete(*rcvr,key)
Case is significant in the matching process.
Example ¶
var aux Auxiliary = make(Auxiliary, 0) aux.Set(`value`, 18) aux.Set(`color`, `red`) aux.Set(`max`, 200) aux.Unset(`max`) fmt.Printf("Len: %d", aux.Len())
Output: Len: 2
type ComparisonOperator ¶
type ComparisonOperator uint8
ComparisonOperator is a uint8 enumerated type used for abstract representation of the following well-known and package-provided operators:
- Equal (=)
- Not Equal (!=)
- Less Than (<)
- Greater Than (>)
- Less Than Or Equal (<=)
- Greater Than Or Equal (>=)
Instances of this type should be passed to Cond as the 'op' value.
const ( Eq ComparisonOperator // 1 (=) Ne // 2 (!=) Lt // 3 (<) Gt // 4 (>) Le // 5 (<=) Ge // 6 (>=) )
ComparisonOperator constants are intended to be used in singular form when evaluating two (2) particular values.
func (ComparisonOperator) Context ¶
func (r ComparisonOperator) Context() string
Context returns the contextual label associated with instances of this type as a string value.
Example ¶
var cop ComparisonOperator = Ge fmt.Printf("Context: %s", cop.Context())
Output: Context: comparison
func (ComparisonOperator) String ¶
func (r ComparisonOperator) String() (op string)
String is a stringer method that returns the string representation of the receiver instance.
Example ¶
var cop ComparisonOperator = Ge fmt.Printf("Operator: %s", cop)
Output: Operator: >=
type Condition ¶
type Condition struct {
// contains filtered or unexported fields
}
Condition describes a single evaluative statement, i.e.:
op | v person = "Jesse" ^ ^ | | kw ex
The keyword (kw) shall always represent an abstract user-defined string construct against which the expression value (ex) is to be evaluated in some manner.
The disposition of the evaluation is expressed through one (1) of several ComparisonOperator (op) instances made available through this package:
- Eq, or "equal to" (=)
- Ne, or "not equal to" (!=)
- Lt, or "less than" (<)
- Le, or "less than or equal" (<=)
- Gt, or "greater than" (>)
- Ge, or "greater than or equal" (>=)
... OR through a user-defined operator that conforms to the package defined Operator interface.
By default, permitted expression (ex) values must honor these guidelines:
- Must be a non-zero string, OR ...
- Must be a valid instance of Stack (or an *alias* of Stack that is convertible back to the Stack type), OR ...
- Must be a valid instance of any type that exports a stringer method (String()) intended to produce the Condition's final expression string representation
However when a PushPolicy function or method is added to an instance of this type, greater control is afforded to the user in terms of what values will be accepted, as well as the quality or state of such values.
Instances of this type -- similar to Stack instances -- MUST be initialized before use. Initialization can occur as a result of executing the Cond package-level function, or using the Init method extended through instances of this type. Initialization state may be checked using the IsInit method.
Example (OneShot) ¶
This example demonstrates the act of a one-shot creation of an instance of Condition using the Cond package-level function. All values must be non-zero/non-nil. This is useful in cases where users have all of the information they need and simply want to fashion a Condition quickly.
Note: line-breaks added for readability; no impact on functionality, so long as dot sequence "connectors" (.) are honored where required.
c := Cond(`person`, Eq, `Jesse`). Paren(). Encap(`"`). NoPadding() fmt.Printf("%s", c)
Output: (person="Jesse")
Example (Procedural) ¶
This example demonstrates the act of procedural assembly of an instance of Condition. The variable c is defined and not initialized. Its values are not set until "later" in the users code, and are set independently of one another.
Note that with this technique a manual call of the Init method is always required as the first action following variable declaration. When using the "one-shot" technique by way of the Cond package-level function, the process of initialization is handled automatically for the user.
var c Condition c.Init() // always init c.Paren() c.SetKeyword(`myKeyword`) c.SetOperator(Eq) c.SetExpression(`value123`) fmt.Printf("%s", c)
Output: ( myKeyword = value123 )
Example (TypeAlias) ¶
This example offers a naïve demonstration of a user-authored type alias for the Condition type.
In a practical scenario, a user would likely want to write custom methods to perform new tasks and/or wrap any existing Condition methods desired in order to avoid the frequent need to cast a custom type to the native stackage.Condition type.
As this is an example, we'll perform a simple cast merely to demonstrate the type was cast successfully.
type customCondition Condition var c Condition = Cond(`keyword`, Ne, `Value`) fmt.Printf("%s (%T)", Condition(customCondition(c)), customCondition(c), )
Output: keyword != Value (stackage.customCondition)
func Cond ¶
Cond returns an instance of Condition bearing the provided component values. This is intended to be used in situations where a Condition instance can be created in one shot.
Example ¶
fmt.Printf("%s", Cond(`π`, Eq, float64(3.141592653589793)))
Output: π = 3.141592653589793
func (Condition) Addr ¶
Addr returns the string representation of the pointer address for the receiver. This may be useful for logging or debugging operations.
Note: this method calls fmt.Sprintf.
Example ¶
This example demonstrates use of the Addr method to obtain the string representation of the memory address for the underlying embedded receiver instance.
NOTE: Since the address will usually be something different each runtime, we can't reliably test this in literal fashion, so we do a simple prefix check as an alternative.
var c Condition c.Init() fmt.Printf("Address prefix valid: %t", c.Addr()[:2] == `0x`) // Address prefix valid: true
Output:
func (Condition) Auxiliary ¶
Auxiliary returns the instance of Auxiliary from within the receiver.
Example ¶
var c Condition c.Init() // one can put anything they wish into this map, // so we'll do a bytes.Buffer since it is simple // and commonplace. var buf *bytes.Buffer = &bytes.Buffer{} _, _ = buf.WriteString(`some .... data .....`) // Create our map (one could also use make // and populate it piecemeal as opposed to // in-line, as we do below). c.SetAuxiliary(map[string]any{ `buffer`: buf, }) // Call our map and call its 'Get' method in one-shot if val, ok := c.Auxiliary().Get(`buffer`); ok { fmt.Printf("%s", val) }
Output: some .... data .....
Example (ByTypeCast) ¶
This example demonstrates building of the Auxiliary map in its generic form (map[string]any) before being type cast to Auxiliary.
var c Condition = Cond(`keyword`, Eq, `value`) proto := make(map[string]any, 0) proto[`value1`] = []int{1, 2, 3, 4, 5} proto[`value2`] = [2]any{float64(7.014), rune('#')} c.SetAuxiliary(Auxiliary(proto)) // cast proto and assign to stack aux := c.Auxiliary() // call map to variable fmt.Printf("%T length:%d", aux, aux.Len())
Output: stackage.Auxiliary length:2
Example (NoInit) ¶
This example demonstrates the call and (failed) set of an uninitialized Auxiliary instance. While no panic ensues, the map instance is not writable.
The user must instead follow the procedures in the WithInit, UserInit or ByTypeCast examples.
var c Condition = Cond(`keyword`, Eq, `value`) aux := c.Auxiliary() fmt.Printf("%T found, length:%d", aux, aux.Set(`testing`, `123`).Len())
Output: stackage.Auxiliary found, length:0
Example (UserInit) ¶
This example demonstrates a scenario similar to that of the WithInit example, except in this case the map instance is entirely created and populated by the user in a traditional fashion.
var c Condition = Cond(`keyword`, Eq, `value`) aux := make(Auxiliary, 0) // user opts to just use standard map // key/val set procedure, and avoids // use of the convenience methods. // This is totally fine. aux[`value1`] = []int{1, 2, 3, 4, 5} aux[`value2`] = [2]any{float64(7.014), rune('#')} c.SetAuxiliary(aux) fmt.Printf("%T length:%d", aux, len(aux))
Output: stackage.Auxiliary length:2
Example (WithInit) ¶
This example continues the concepts within the NoInit example, except in this case proper initialization occurs and a desirable outcome is achieved.
var c Condition = Cond(`keyword`, Eq, `value`) c.SetAuxiliary() // auto-init aux := c.Auxiliary() fmt.Printf("%T found, length was:%d, is now:%d", aux, aux.Len(), // check initial (pre-set) length aux.Set(`testing`, `123`).Len()) // fluent Set/Len in one shot
Output: stackage.Auxiliary found, length was:0, is now:1
func (Condition) CanNest ¶
CanNest returns a Boolean value indicative of whether the no-nesting bit is unset, thereby allowing a Stack or Stack type alias instance to be set as the value.
See also the IsNesting method.
Example ¶
c := Cond(`π`, Eq, float64(3.14159265358979323)) c.NoNesting(true) fmt.Printf("Can nest: %t", c.CanNest())
Output: Can nest: false
func (Condition) Category ¶
Category returns the categorical label string value assigned to the receiver, if set, else a zero string.
Example ¶
c := Cond(`π`, Eq, float64(3.14159265358979323)) c.SetCategory(`mathematical constant`) fmt.Printf("Category: %s", c.Category())
Output: Category: mathematical constant
func (Condition) Encap ¶
Encap accepts input characters for use in controlled condition value encapsulation. Acceptable input types are:
A single string value will be used for both L and R encapsulation.
An instance of []string with two (2) values will be used for L and R encapsulation using the first and second slice values respectively.
An instance of []string with only one (1) value is identical to the act of providing a single string value, in that both L and R will use one value.
Example (DoubleQuote) ¶
var c Condition c.Init() c.SetKeyword(`key`) c.SetOperator(Eq) c.SetExpression(`value`) c.Encap(`"`) fmt.Printf("%s", c)
Output: key = "value"
Example (Tag) ¶
var c Condition c.Init() c.SetKeyword(`key`) c.SetOperator(Eq) c.SetExpression(`value`) c.Encap([]string{`<`, `>`}) fmt.Printf("%s", c)
Output: key = <value>
func (Condition) Err ¶
Err returns the error residing within the receiver, or nil if no error condition has been declared.
This method will be particularly useful for users who do not care for fluent-style operations and would instead prefer to operate in a more procedural fashion.
Note that a chained sequence of method calls of this type shall potentially obscure error conditions along the way, as each successive method may happily overwrite any error instance already present.
Example ¶
var c Condition = Cond(``, ComparisonOperator(7), `ThisIsBogus`) fmt.Printf("%v", c.Err())
Output: keyword value is zero
func (Condition) Evaluate ¶
Evaluate uses the Evaluator closure function to apply the value (x) to the receiver in order to conduct a matching/assertion test or analysis for some reason. This is entirely up to the user.
A Boolean value returned indicative of the result. Note that if an instance of Evaluator was not assigned to the Condition prior to execution of this method, the return value shall always be false.
Example ¶
This example demonstrates the use of the Evaluate method to execute an Evaluator instance assigned using the Set Evaluator method.
degrees := float64(83.1) c := Cond(`degrees`, Eq, degrees) // we don't really need input values for // this one, since we read directly from // the Condition instance c. And we don't // need an error value since this is just // an example, therefore we use shadowing // (_) as needed. c.SetEvaluator(func(_ ...any) (R any, _ error) { expr := c.Expression() D, _ := expr.(float64) // Don't shadow 'ok' in real-life. // I could have imported "math", // but this is all we need. pi := 3.14159265358979323846264338327950288419716939937510582097494459 R = float64(D*pi) / 180 return }) radians, _ := c.Evaluate() fmt.Printf("%.02f° x π/180° = %.02frad", degrees, radians.(float64))
Output: 83.10° x π/180° = 1.45rad
func (Condition) Expression ¶
Expression returns the expression value(s) stored within the receiver, or nil if unset. A valid receiver instance MUST always possess a non-nil expression value.
Example ¶
var c Condition c.Init() c.SetKeyword(`key`) c.SetOperator(Eq) c.SetExpression(`value`) fmt.Printf("%s", c.Expression())
Output: value
func (Condition) ID ¶
Name returns the name of the receiver instance, if set, else a zero string will be returned. The presence or lack of a name has no effect on any of the receiver's mechanics, and is strictly for convenience.
Example ¶
c := Cond(`π`, Eq, float64(3.14159265358979323)) c.SetID(`pi`) fmt.Printf("ID: %s", c.ID())
Output: ID: pi
func (*Condition) Init ¶
Init will [re-]initialize the receiver's contents and return them to an unset, but assignable, state. This is a destructive method: the embedded pointer within the receiver instance shall be totally annihilated.
This method is niladic and fluent in nature. No input is required, and the only element returned is the receiver itself.
This method may be useful in situations where a Condition will be assembled in a "piecemeal" fashion (i.e.: incrementally), or if a Condition instance is slated to be repurposed for use elsewhere (possibly in a repetative manner).
Example ¶
var c Condition c.Init() fmt.Printf("%T is initialized: %t", c, c.IsInit())
Output: stackage.Condition is initialized: true
func (Condition) IsEncap ¶
IsEncap returns a Boolean value indicative of whether value encapsulation characters have been set within the receiver.
Example ¶
var c Condition = Cond(`key`, Eq, `value`) c.Encap([]string{`<`, `>`}) fmt.Printf("%T expression is encapsulated: %t", c, c.IsEncap())
Output: stackage.Condition expression is encapsulated: true
func (Condition) IsFIFO ¶
IsFIFO returns a Boolean value indicative of whether the underlying receiver instance's Expression value represents a Stack (or Stack type alias) instance which exhibits First-In-First-Out behavior as it pertains to the act of appending and truncating the receiver's slices.
A value of false implies that no such Stack instance is set as the expression, OR that the Stack exhibits Last-In-Last-Out behavior, which is the default ingress/egress scheme imposed upon instances of this type.
Example ¶
valueStack := And().SetFIFO(true).Push(`this`, `that`, `other`) c := Cond(`stack`, Eq, valueStack) fmt.Printf("%T is First-In/First-Out: %t", c, c.IsFIFO())
Output: stackage.Condition is First-In/First-Out: true
func (Condition) IsInit ¶
IsInit will verify that the internal pointer instance of the receiver has been properly initialized. This method executes a preemptive execution of the IsZero method.
Example ¶
var c Condition fmt.Printf("%T is initialized: %t", c, c.IsInit())
Output: stackage.Condition is initialized: false
func (Condition) IsNesting ¶
IsNesting returns a Boolean value indicative of whether the underlying expression value is either a Stack or Stack type alias. If true, this indicates the expression value descends into another hierarchical (nested) context.
Example ¶
valueStack := And().Push(`this`, `that`, `other`) c := Cond(`stack`, Eq, valueStack) fmt.Printf("%T is nesting: %t", c, c.IsNesting())
Output: stackage.Condition is nesting: true
func (Condition) IsPadded ¶
IsPadded returns a Boolean value indicative of whether the receiver pads its contents with a SPACE char (ASCII #32).
Example ¶
c := Cond(`keyword`, Eq, `value`) fmt.Printf("%T is padded: %t", c, c.IsPadded())
Output: stackage.Condition is padded: true
func (Condition) IsParen ¶
IsParen returns a Boolean value indicative of whether the receiver is parenthetical.
Example ¶
var c Condition c.Init() c.Paren() // toggle to true from false default c.SetKeyword(`keyword`) c.SetOperator(Ge) c.SetExpression(1.456) fmt.Printf("Is parenthetical: %t", c.IsParen())
Output: Is parenthetical: true
func (Condition) IsZero ¶
IsZero returns a Boolean value indicative of whether the receiver is nil, or unset.
Example ¶
var c Condition fmt.Printf("Zero: %t", c.IsZero())
Output: Zero: true
func (Condition) Keyword ¶
Keyword returns the Keyword interface type instance found within the receiver.
Example ¶
var c Condition c.Init() c.SetKeyword(`my_keyword`) fmt.Printf("Keyword: %s", c.Keyword())
Output: Keyword: my_keyword
func (Condition) Len ¶
Len returns a "perceived" abstract length relating to the content (or lack thereof) assigned to the receiver instance:
- An uninitialized or zero instance returns zero (0)
- An initialized instance with no Expression assigned (nil) returns zero (0)
- A Stack or Stack type alias assigned as the Expression shall impose its own stack length as the return value (even if zero (0))
All other type instances assigned as an Expression shall result in a return of one (1); this includes slice types, maps, arrays and any other type that supports multiple values.
This capability was added to this type to mirror that of the Stack type in order to allow additional functionality to be added to the Interface interface.
Example ¶
var c Condition c.Init() c.Paren() // toggle to true from false default c.SetKeyword(`keyword`) c.SetOperator(Ge) noLen := c.Len() c.SetExpression(`just_a_string`) strLen := c.Len() // Overwrite the above string // with a stack containing // three (3) strings. S := And().Push(`this`, `won't`, `work`) c.SetExpression(S) stkLen := c.Len() fmt.Printf("length with nothing: %d\nlength with string: %d\nlength with %T: %d", noLen, strLen, S, stkLen)
Output: length with nothing: 0 length with string: 1 length with stackage.Stack: 3
func (Condition) LogLevels ¶
LogLevels returns the string representation of a comma-delimited list of all active LogLevel values within the receiver.
Example ¶
var buf *bytes.Buffer = &bytes.Buffer{} var customLogger *log.Logger = log.New(buf, ``, 0) var c Condition c.Init() c.SetLogger(customLogger) c.SetLogLevel(LogLevel1, LogLevel3) fmt.Printf("Loglevels: %s", c.LogLevels())
Output: Loglevels: CALLS,STATE
func (Condition) Logger ¶
Logger returns the *log.Logger instance. This can be used for quick access to the log.Logger type's methods in a manner such as:
r.Logger().Fatalf("We died")
It is not recommended to modify the return instance for the purpose of disabling logging outright (see Stack.SetLogger method as well as the SetDefaultConditionLogger package-level function for ways of doing this easily).
Example ¶
var buf *bytes.Buffer = &bytes.Buffer{} var customLogger *log.Logger = log.New(buf, ``, 0) var c Condition c.Init() c.SetLogger(customLogger) fmt.Printf("%T", c.Logger())
Output: *log.Logger
func (Condition) NoNesting ¶
NoNesting sets the no-nesting bit within the receiver. If set to true, the receiver shall ignore any Stack or Stack type alias instance when assigned using the SetExpression method. In such a case, only primitives, etc., shall be honored during the SetExpression operation.
A Boolean input value explicitly sets the bit as intended. Execution without a Boolean input value will *TOGGLE* the current state of the nesting bit (i.e.: true->false and false->true)
Example ¶
var c Condition c.Init() c.Paren() // toggle to true from false default c.SetKeyword(`keyword`) c.SetOperator(Ge) c.NoNesting(true) c.SetExpression( And().Push(`this`, `won't`, `work`), ) fmt.Printf("%v", c.Expression())
Output: <nil>
func (Condition) NoPadding ¶
NoPadding sets the no-space-padding bit within the receiver. String values within the receiver shall not be padded using a single space character (ASCII #32).
A Boolean input value explicitly sets the bit as intended. Execution without a Boolean input value will *TOGGLE* the current state of the quotation bit (i.e.: true->false and false->true)
Example ¶
var c Condition c.Init() c.NoPadding(true) c.SetKeyword(`keyword`) c.SetOperator(Ge) c.SetExpression(`expression`) fmt.Printf("%s", c)
Output: keyword>=expression
func (Condition) Operator ¶
Operator returns the Operator interface type instance found within the receiver.
Example ¶
var c Condition c.Init() c.SetKeyword(`keyword`) c.SetOperator(Ge) c.SetExpression(1.456) fmt.Printf("Operator: %s", c.Operator())
Output: Operator: >=
func (Condition) Paren ¶
Paren sets the string-encapsulation bit for parenthetical expression within the receiver. The receiver shall undergo parenthetical encapsulation ( (...) ) during the string representation process. Individual string values shall not be encapsulated in parenthesis, only the whole (current) stack.
A Boolean input value explicitly sets the bit as intended. Execution without a Boolean input value will *TOGGLE* the current state of the encapsulation bit (i.e.: true->false and false->true)
Example ¶
var c Condition c.Init() c.Paren() // toggle to true from false default c.SetKeyword(`keyword`) c.SetOperator(Ge) c.SetExpression(1.456) fmt.Printf("%s", c)
Output: ( keyword >= 1.456 )
func (Condition) SetAuxiliary ¶
SetAuxiliary assigns aux, as initialized and optionally populated as needed by the user, to the receiver instance. The aux input value may be nil.
If no variadic input is provided, the default Auxiliary allocation shall occur.
Note that this method shall obliterate any instance that may already be present, regardless of the state of the input value aux.
Example ¶
var c Condition c.Init() // alloc map aux := make(Auxiliary, 0) // populate map aux.Set(`somethingWeNeed`, struct { Type string Value []string }{ Type: `L`, Value: []string{ `abc`, `def`, }, }) // assign map to condition rcvr c.SetAuxiliary(aux) // verify presence call := c.Auxiliary() fmt.Printf("%T found, length:%d", call, call.Len())
Output: stackage.Auxiliary found, length:1
func (Condition) SetCategory ¶
SetCategory assigns the provided string to the receiver internal category value. This allows for a means of identifying a particular kind of Condition in the midst of many.
Example ¶
c := Cond(`π`, Eq, float64(3.14159265358979323)) c.SetCategory(`mathematical constant`) fmt.Printf("Category: %s", c.Category())
Output: Category: mathematical constant
func (Condition) SetErr ¶
SetErr sets the underlying error value within the receiver to the assigned input value err, whether nil or not.
This method may be most valuable to users who have chosen to extend this type by aliasing, and wish to control the handling of error conditions in another manner.
Example ¶
This example demonstrates use of the Condition.SetErr method to assign a custom error to the receiver. This is useful in cases where custom processing is being conducted, and a custom error needs to be preserved and accessible to the caller.
var c Condition = Cond(`mySupposedly`, Eq, `validCondition`) c.SetErr(fmt.Errorf("Hold on there buddy, this is garbage")) fmt.Printf("%v", c.Err())
Output: Hold on there buddy, this is garbage
Example (Clear) ¶
This example demonstrates use of the Condition.SetErr method to clear an error instance from the receiver. This may be useful in the event that a problem has potentially been solved and a re-run of testing is needed.
var c Condition = Cond(`mySupposedly`, Eq, `validCondition`) c.SetErr(nil) fmt.Printf("Nil: %t", c.Err() == nil)
Output: Nil: true
func (Condition) SetEvaluator ¶
SetEvaluator assigns the instance of Evaluator to the receiver. This will allow the Evaluate method to return a more meaningful result.
Specifying nil shall disable this capability if enabled.
Example ¶
This example demonstrates the use of the SetEvaluator method to assign an instance of the Evaluator closure signature to the receiver instance, allowing the creation and return of a value based upon some procedure defined by the user.
Specifically, the code below demonstrates the conversion a degree value to a radian value using the formula shown in the example below:
degrees := float64(83.1) c := Cond(`degrees`, Eq, degrees) // we don't really need input values for // this one, since we read directly from // the Condition instance c. And we don't // need an error value since this is just // an example, therefore we use shadowing // (_) as needed. c.SetEvaluator(func(_ ...any) (R any, _ error) { expr := c.Expression() D, _ := expr.(float64) // Don't shadow 'ok' in real-life. // I could have imported "math", // but this is all we need. pi := 3.14159265358979323846264338327950288419716939937510582097494459 R = float64(D*pi) / 180 return }) radians, _ := c.Evaluate() fmt.Printf("%.02f° x π/180° = %.02frad", degrees, radians.(float64))
Output: 83.10° x π/180° = 1.45rad
func (Condition) SetExpression ¶
SetExpression sets the receiver's expression value(s) using the specified ex input argument.
Example ¶
var c Condition c.Init() c.SetKeyword(`keyword`) c.SetOperator(Ge) c.SetExpression(1.456) fmt.Printf("Expr type: %T", c.Expression())
Output: Expr type: float64
func (Condition) SetID ¶
SetID assigns the provided string value (or lack thereof) to the receiver. This is optional, and is usually only needed in complex Condition structures in which "labeling" certain components may be advantageous. It has no effect on an evaluation, nor should a name ever cause a validity check to fail.
If the string `_random` is provided, a 24-character alphanumeric string is randomly generated using math/rand and assigned as the ID.
Example ¶
c := Cond(`π`, Eq, float64(3.14159265358979323)) c.SetID(`pi`) fmt.Printf("ID: %s", c.ID())
Output: ID: pi
Example (PointerAddress) ¶
var c Condition = Cond(`keyword`, Ne, `bogus`) // can't predict what ID will be, // so we'll check the prefix to // be certain it begins with '0x'. c.SetID(`_addr`) fmt.Printf("Address ID has '0x' prefix: %t", c.ID()[:2] == `0x`)
Output: Address ID has '0x' prefix: true
Example (Random) ¶
var c Condition = Cond(`keyword`, Ne, `bogus`) // can't predict what ID will // be, so we'll check length // which should always be 24. c.SetID(`_random`) fmt.Printf("Random ID len: %d", len(c.ID()))
Output: Random ID len: 24
func (Condition) SetKeyword ¶
SetKeyword sets the receiver's keyword using the specified kw input argument.
Example ¶
var c Condition c.Init() c.SetKeyword(`my_keyword`) fmt.Printf("Keyword: %s", c.Keyword())
Output: Keyword: my_keyword
func (Condition) SetLogLevel ¶
SetLogLevel enables the specified LogLevel instance(s), thereby instructing the logging subsystem to accept events for submission and transcription to the underlying logger.
Users may also sum the desired bit values manually, and cast the product as a LogLevel. For example, if STATE (4), DEBUG (8) and TRACE (32) logging were desired, entering LogLevel(44) would be the same as specifying LogLevel3, LogLevel4 and LogLevel6 in variadic fashion.
Example ¶
var buf *bytes.Buffer = &bytes.Buffer{} var customLogger *log.Logger = log.New(buf, ``, 0) var c Condition c.Init() c.SetLogger(customLogger) c.SetLogLevel(LogLevel1, LogLevel3) // calls (1) + state(4) fmt.Printf("LogLevels active: %s", c.LogLevels())
Output: LogLevels active: CALLS,STATE
func (Condition) SetLogger ¶
SetLogger assigns the specified logging facility to the receiver instance.
Logging is available but is set to discard all events by default.
An active logging subsystem within the receiver supercedes the default package logger.
The following types/values are permitted:
- string: `none`, `off`, `null`, `discard` will turn logging off
- string: `stdout` will set basic STDOUT logging
- string: `stderr` will set basic STDERR logging
- int: 0 will turn logging off
- int: 1 will set basic STDOUT logging
- int: 2 will set basic STDERR logging
- *log.Logger: user-defined *log.Logger instance will be set; it should not be nil
Case is not significant in the string matching process.
Logging may also be set globally using the SetDefaultLogger package level function. Similar semantics apply.
func (Condition) SetOperator ¶
SetOperator sets the receiver's comparison operator using the specified Operator-qualifying input argument (op).
Example ¶
var c Condition c.Init() c.SetKeyword(`keyword`) c.SetOperator(Ge) c.SetExpression(1.456) fmt.Printf("Operator: %s", c.Operator())
Output: Operator: >=
func (Condition) SetPresentationPolicy ¶
func (r Condition) SetPresentationPolicy(x PresentationPolicy) Condition
SetPresentationPolicy assigns the instance of PresentationPolicy to the receiver. This will allow the user to leverage their own "stringer" method for automatic use when this type's String method is called.
Specifying nil shall disable this capability if enabled.
Example ¶
This example demonstrates a custom user-authored stringer that assumes full responsibility for the string representation of a Condition instance.
Here, we import "encoding/base64" to decode a string into the true underlying value prior to calling fmt.Sprintf to present and return the preferred string value.
// create a Condition and set a custom // ppolicy to handle base64 encoded // values. myCondition := Cond(`keyword`, Eq, `MTM4NDk5`) myCondition.SetPresentationPolicy(func(x ...any) string { val := myCondition.Expression().(string) decoded, err := base64.StdEncoding.DecodeString(val) if err != nil { myCondition.SetErr(err) //fmt.Printf("%v", err) // optional return `invalid_condition` } // optional //myCondition.SetExpression(decoded) // return new string value return fmt.Sprintf("%v %v %v", myCondition.Keyword(), myCondition.Operator(), string(decoded), ) }) fmt.Printf("%s", myCondition)
Output: keyword = 138499
func (Condition) SetValidityPolicy ¶
func (r Condition) SetValidityPolicy(x ValidityPolicy) Condition
SetValidityPolicy assigns the instance of ValidityPolicy to the receiver. This will allow the Valid method to return a more meaningful result.
Specifying nil shall disable this capability if enabled.
Example ¶
myCondition := Cond(`keyword`, Eq, int(3)) myCondition.SetValidityPolicy(func(_ ...any) (err error) { assert, _ := myCondition.Expression().(int) if assert%2 != 0 { err = fmt.Errorf("%T is not even (%d)", assert, assert) } return }) fmt.Printf("%v", myCondition.Valid())
Output: int is not even (3)
func (Condition) String ¶
String is a stringer method that returns the string representation of the receiver instance. It will only function if the receiver is in good standing, and passes validity checks.
Note that if the underlying expression value is not a known type, such as a Stack or a Go primitive, this method may be uncertain as to what it should do. A bogus string may be returned.
In such a case, it may be necessary to subvert the default string representation behavior demonstrated by instances of this type in favor of a custom instance of the PresentationPolicy closure type for maximum control.
Example ¶
c := Cond(`person`, Eq, `Jesse`). Paren(). Encap(`"`). NoPadding() fmt.Printf("%s", c)
Output: (person="Jesse")
func (Condition) UnsetLogLevel ¶
UnsetLogLevel disables the specified LogLevel instance(s), thereby instructing the logging subsystem to discard events submitted for transcription to the underlying logger.
Example ¶
var buf *bytes.Buffer = &bytes.Buffer{} var customLogger *log.Logger = log.New(buf, ``, 0) var c Condition c.Init() c.SetLogger(customLogger) c.SetLogLevel(LogLevel1, LogLevel3) // calls (1) + state(4) c.UnsetLogLevel(LogLevel1) // -1 fmt.Printf("LogLevels active: %s", c.LogLevels())
Output: LogLevels active: STATE
func (Condition) Valid ¶
Valid returns an instance of error, identifying any serious issues perceived with the state of the receiver.
Non-serious (interim) errors such as denied pushes, capacity violations, etc., are not shown by this method.
If a ValidityPolicy was set within the receiver, it shall be executed here. If no ValidityPolicy was specified, only elements pertaining to basic viability are checked.
Example ¶
c := Cond(`person`, Eq, `Jesse`). Paren(). Encap(`"`). NoPadding() fmt.Printf("Valid: %t", c.Valid() == nil)
Output: Valid: true
type Evaluator ¶
Evaluator is a first-class function signature type which may be leveraged by users in order to compose matching functions by which a given Condition shall be measured/compared, etc.
In other words, this type takes this package one step forward: it no longer merely creates various expressions in the abstract sense -- now it will actually *apply* them to real values, or to gauge their verisimilitude in some other manner. The catch is that the user will need to author the needed functions in order to make such determinations practical.
Use of this feature is totally optional, and may be overkill for most users.
The signature allows for variadic input of any type(s), and shall require the return of a single any instance alongside an error. The contents of the return 'any' instance (if not nil) is entirely up to the user.
type Interface ¶
type Interface interface { // Stack: Len returns an integer that represents the number of // slices present within. // // Condition: Len returns a one (1) if properly initialized // and set with a value that is not a Stack. Len returns a // zero (0) if invalid or otherwise not properly initialized. // Len returns the value of Stack.Len in deference, should the // expression itself be a Stack. Len() int // IsInit returns a Boolean value indicative of whether the // receiver instance is considered 'properly initialized' IsInit() bool // Stack: IsFIFO returns a Boolean value indicative of whether // the Stack instance exhibits First-In-First-Out behavior as it // pertains to the ingress and egress order of slices. See the // Stack.SetFIFO method for details on setting this behavior. // // Condition: IsFIFO returns a Boolean value indicative of whether // the receiver's Expression value contains a Stack instance AND // that Stack exhibits First-In-First-Out behavior as it pertains // to the ingress and egress order of slices. If no Stack value is // present within the Condition, false is always returned. IsFIFO() bool // IsZero returns a Boolean value indicative of whether the receiver // instance is considered nil, or unset. IsZero() bool // Stack: CanNest returns a Boolean value indicative of whether the // receiver is allowed to append (Push) additional Stack instances // into its collection of slices. // // Condition: CanNest returns a Boolean value indicative of whether // the receiver is allowed to set a Stack instance as its Expression // value. // // See also the NoNesting and IsNesting methods for either of these // types. CanNest() bool // IsParen returns a Boolean value indicative of whether the receiver // instance, when represented as a string value, shall encapsulate in // parenthetical L [(] and R [)] characters. // // See also the Paren method for Condition and Stack instances. IsParen() bool // IsEncap returns a Boolean value indicative of whether the receiver // instance, when represented as a string value, shall encapsulate the // effective value within user-defined quotation characters. // // See also the Encap method for Condition and Stack instances. IsEncap() bool // Stack: IsPadded returns a Boolean value indicative of whether WHSP // (ASCII #32) padding shall be applied to the outermost ends of the // string representation of the receiver (but within parentheticals). // // Condition: IsPadded returns a Boolean value indicative of whether // WHSP (ASCII #32) padding shall be applied to the outermost ends of // the string representation of the receiver, as well as around it's // comparison operator, when applicable. // // See also the NoPadding method for either of these types. IsPadded() bool // Stack: IsNesting returns a Boolean value indicative of whether the // receiver contains one (1) or more slices that are Stack instances. // // Condition: IsNesting returns a Boolean value indicative of whether // the Expression value set within the receiver is a Stack instance. // // See also the NoNesting and CanNest method for either of these types. IsNesting() bool // ID returns the identifier assigned to the receiver, if set. This // may be anything the user chooses to set, or it may be auto-assigned // using the `_addr` or `_random` input keywords. // // See also the SetID method for Condition and Stack instances. ID() string // Addr returns the string representation of the pointer address of // the embedded receiver instance. This is mainly useful in cases // where debugging/troubleshooting may be underway, and the ability // to distinguish unnamed instances would be beneficial. It may also // be used as an alternative to the tedium of manually naming objects. Addr() string // String returns the string representation of the receiver. Note that // if the receiver is a BASIC Stack, string representation shall not be // possible. String() string // Stack: Category returns the categorical string label assigned to the // receiver instance during initialization. This will be one of AND, OR, // NOT, LIST and BASIC (these values may be folded case-wise depending // on the state of the Fold bit, as set by the user). // // Condition: Category returns the categorical string label assigned to // the receiver instance by the user at any time. Condition categorical // labels are entirely user-controlled. // // See also the SetCategory method for either of these types. Category() string // Err returns the most recently set instance of error within the receiver. // This is particularly useful for users who dislike fluent-style method // execution and would prefer to operate in the traditional "if err != nil ..." // style. // // See also the SetErr method for Condition and Stack instances. Err() error // Valid returns an instance of error resulting from a cursory review of the // receiver without any special context. Nilness, quality-of-initialization // and other rudiments are checked. // // This method is most useful when users apply a ValidityPolicy method or // function to the receiver instance, allowing full control over what they // deem "valid". See the SetValidityPolicy method for Condition and Stack // instances for details. Valid() error // Logger returns the underlying instance of *log.Logger, which may be set by // the package by defaults, or supplied by the user in a piecemeal manner. // // See also the SetLogger method for Condition and Stack instances. Logger() *log.Logger }
Interface is an interface type qualified through instances of the following types (whether native, or type-aliased):
- Stack
- Condition
This interface type offers users an alternative to the tedium of repeated type assertion for every Stack and Condition instance they encounter. This may be particularly useful in situations where the act of traversal is conducted upon a Stack instance that contains myriad hierarchies and nested contexts of varying types.
This is not a complete "replacement" for the explicit use of package defined types nor their aliased counterparts. The Interface interface only extends methods that are read-only in nature AND common to both of the above categories.
To access the entire breadth of available methods for the underlying type instance, manual type assertion shall be necessary.
Users SHOULD adopt this interface signature for use in their solutions if and when needed, though it is not a requirement.
type LogLevel ¶
type LogLevel uint16
LogLevel is a uint16 type alias used to define compound logging verbosity configuration values.
LogLevel consts zero (0) through four (4) are as follows:
- NoLogLevels defines the lack of any logging level
- LogLevel1 defines basic function and method call event logging
- LogLevel2 defines the logging of events relating to configuration state changes
- LogLevel3
- LogLevel4
const ( LogLevel1 LogLevel = 1 << iota // 1 :: builtin: calls LogLevel2 // 2 :: builtin: policy LogLevel3 // 4 :: builtin: state LogLevel4 // 8 :: builtin: debug LogLevel5 // 16 :: builtin: errors LogLevel6 // 32 :: builtin: trace UserLogLevel1 // 64 :: user-defined UserLogLevel2 // 128 :: user-defined UserLogLevel3 // 256 :: user-defined UserLogLevel4 // 512 :: user-defined UserLogLevel5 // 1024 :: user-defined UserLogLevel6 // 2048 :: user-defined UserLogLevel7 // 4096 :: user-defined UserLogLevel8 // 8192 :: user-defined UserLogLevel9 // 16384 :: user-defined UserLogLevel10 // 32768 :: user-defined AllLogLevels LogLevel = ^LogLevel(0) // 65535 :: log all of the above unconditionally (!!) )
const NoLogLevels LogLevel = 0 // silent
type Operator ¶
type Operator interface { // String should return the preferred string // representation of the Operator instance. // This is ultimately the value that shall be // used during the string representation of // the instance of Condition to which the // Operator is assigned. Generally, this will // be something short and succinct (e.g.: `~=`) // but can conceivably be anything you want. String() string // Context returns the string representation // of the context behind the operator. As an // example, the Context for an instance of // ComparisonOperator is `comparison`. Users // should choose intuitive, helpful context // names for custom types when defining them. Context() string }
Operator is an interface type that allows user-defined operators to be used within instances of Condition. In rare cases, users may wish to utilize operators that go beyond the package provided ComparisonOperator definitions (or just represent the same operators in a different way). Defining types that conform to the signature of this interface type allows just that.
type PresentationPolicy ¶
PresentationPolicy is a first-class (closure) function signature that may be leveraged by users in order to better control value presentation during the string representation process. Essentially, one may write their own "stringer" (String()) function or method and use it to override the default behavior of the package based String method(s).
Note that basic Stack instances are ineligible for the process of string representation, thus no PresentationPolicy may be set.
type PushPolicy ¶
PushPolicy is a first-class (closure) function signature that may be leveraged by users in order to control what types instances may be pushed into a Stack instance when using its 'Push' method.
When authoring functions or methods that conform to this signature, the idea is to return true for any value that should be pushed, and false for all others. This allows for an opportunity to interdict potentially undesirable Stack additions, unsupported types, etc.
A PushPolicy function or method is executed for each element being added to a Stack via its Push method.
type Stack ¶
type Stack struct {
// contains filtered or unexported fields
}
Stack embeds slices of any ([]any) in pointer form and extends methods allowing convenient interaction with stack structures.
func And ¶
And initializes and returns a new instance of Stack configured as a Boolean ANDed stack.
Example (SymbolicAnd) ¶
This example demonstrates ANDed stack values using the double ampersand (&&) symbol.
and := And(). Paren(). // Add parenthesis Symbol(`&&`). // Use double pipes for OR Push(`condition1`, `condition2`, `condition3`) // Push these values now fmt.Printf("%s\n", and)
Output: ( condition1 && condition2 && condition3 )
func Basic ¶
Basic initializes and returns a new instance of Stack, set for basic operation only.
Please note that instances of this design are not eligible for string representation, value encaps, delimitation, and other presentation-related string methods. As such, a zero string (“) shall be returned should String() be executed.
PresentationPolicy instances cannot be assigned to Stack instances of this design.
Example ¶
This example demonstrates the creation of a basic stack and a call to its first (0th) index. Type assertion is performed to reveal a float64 instance.
b := Basic() b.Push( float64(3.14159), float64(-9.378), ) idx, _ := b.Index(0) // call index assert, _ := idx.(float64) // type assert to float64 fmt.Printf("%.02f", assert)
Output: 3.14
Example (SetAsReadOnly) ¶
This example demonstrates the creation of a basic stack with (and without) read-only controls enabled.
b := Basic() b.Push( float64(3.14159), float64(-9.378), ) b.ReadOnly() // set readonly b.Remove(1) // this ought to fail ... //b.Pop() // alternative to b.Remove(1) in this case first := b.Len() // record len b.ReadOnly() // unset readonly b.Remove(1) // retry removal second := b.Len() // record len again fmt.Printf("first try: %d vs. second try: %d", first, second)
Output: first try: 2 vs. second try: 1
Example (WithCapacity) ¶
This example demonstrates the creation of a basic stack and an enforced capacity constraint.
b := Basic(2) b.Push( float64(3.14159), float64(-9.378), float64(139.104), ) fmt.Printf("%d", b.Len())
Output: 2
func List ¶
List initializes and returns a new instance of Stack configured as a simple list. Stack instances of this design can be delimited using the SetDelimiter method.
Example ¶
This example demonstrates the creation of a List stack, a stack type suitable for general use.
l := List().Push( 1.234, 1+3i, `hello mr thompson`, ) l.SetDelimiter('?') // alternatives ... //l.JoinDelim(`,`) //strings ok too! //l.JoinDelim(`delim`) fmt.Printf("%s", l)
Output: 1.234 ? (1+3i) ? hello mr thompson
func Or ¶
Or initializes and returns a new instance of Stack configured as a Boolean ORed stack.
Example (SymbolicOr) ¶
This example demonstrates ORed stack values using the double pipe (||) symbol and custom value encapsulation.
or := Or(). Paren(). // Add parenthesis Symbol(`||`). // Use double pipes for OR Encap(` `, `"`). // Encapsulate individual vals with double-quotes surrounded by spaces Push(`cn`, `sn`, `givenName`, `objectClass`, `uid`) // Push these values now fmt.Printf("%s\n", or)
Output: ( "cn" || "sn" || "givenName" || "objectClass" || "uid" )
func (Stack) Addr ¶
Addr returns the string representation of the pointer address for the receiver. This may be useful for logging or debugging operations.
Note: this call uses fmt.Sprintf.
Example ¶
var c Stack = List().Push(`this`, `and`, `that`) fmt.Printf("Address ID has '0x' prefix: %t", c.Addr()[:2] == `0x`)
Output: Address ID has '0x' prefix: true
func (Stack) Auxiliary ¶
Auxiliary returns the instance of Auxiliary from within the receiver.
Example ¶
// make a stack ... any type would do l := List().Push(`this`, `that`, `other`) // one can put anything they wish into this map, // so we'll do a bytes.Buffer since it is simple // and commonplace. var buf *bytes.Buffer = &bytes.Buffer{} _, _ = buf.WriteString(`some .... data .....`) // Create our map (one could also use make // and populate it piecemeal as opposed to // in-line, as we do below). l.SetAuxiliary(map[string]any{ `buffer`: buf, }) // Call our map and call its 'Get' method in one-shot if val, ok := l.Auxiliary().Get(`buffer`); ok { fmt.Printf("%s", val) }
Output: some .... data .....
Example (ByTypeCast) ¶
This example demonstrates building of the Auxiliary map in its generic form (map[string]any) before being type cast to Auxiliary.
var list Stack = List() proto := make(map[string]any, 0) proto[`value1`] = []int{1, 2, 3, 4, 5} proto[`value2`] = [2]any{float64(7.014), rune('#')} list.SetAuxiliary(Auxiliary(proto)) // cast proto and assign to stack aux := list.Auxiliary() // call map to variable fmt.Printf("%T length:%d", aux, aux.Len())
Output: stackage.Auxiliary length:2
Example (NoInit) ¶
This example demonstrates the call and (failed) set of an uninitialized Auxiliary instance. While no panic ensues, the map instance is not writable.
The user must instead follow the procedures in the WithInit, UserInit or ByTypeCast examples.
var list Stack = List() aux := list.Auxiliary() fmt.Printf("%T found, length:%d", aux, aux.Set(`testing`, `123`).Len())
Output: stackage.Auxiliary found, length:0
Example (UserInit) ¶
This example demonstrates a scenario similar to that of the WithInit example, except in this case the map instance is entirely created and populated by the user in a traditional fashion.
var list Stack = List() aux := make(Auxiliary, 0) // user opts to just use standard map // key/val set procedure, and avoids // use of the convenience methods. // This is totally fine. aux[`value1`] = []int{1, 2, 3, 4, 5} aux[`value2`] = [2]any{float64(7.014), rune('#')} list.SetAuxiliary(aux) fmt.Printf("%T length:%d", aux, len(aux))
Output: stackage.Auxiliary length:2
Example (WithInit) ¶
This example continues the concepts within the NoInit example, except in this case proper initialization occurs and a desirable outcome is achieved.
var list Stack = List().SetAuxiliary() // no args triggers auto-init aux := list.Auxiliary() fmt.Printf("%T found, length was:%d, is now:%d", aux, aux.Len(), // check initial (pre-set) length aux.Set(`testing`, `123`).Len()) // fluent Set/Len in one shot
Output: stackage.Auxiliary found, length was:0, is now:1
func (Stack) Avail ¶
Avail returns the available number of slices as an integer value by subtracting the current length from a non-zero capacity.
If no capacity is set, this method returns minus one (-1), meaning infinite capacity is available.
If the receiver (r) is uninitialized, zero (0) is returned.
func (Stack) CanMutex ¶
CanMutex returns a Boolean value indicating whether the receiver instance has been equipped with mutual exclusion locking features.
This does NOT indicate whether the receiver is actually locked.
func (Stack) CanNest ¶
CanNest returns a Boolean value indicative of whether the no-nesting bit is unset, thereby allowing the Push of Stack and/or Stack type alias instances.
See also the IsNesting method.
func (Stack) Cap ¶
Cap returns the integer representation of a capacity limit imposed upon the receiver. The return values shall be interpreted as follows:
- A zero (0) value indicates that the receiver has NO capacity, as the instance is not properly initialized
- A positive non-zero value (e.g.: >=1) reflects the capacity limit imposed upon the receiver instance
- A minus one (-1) value indicates infinite capacity is available; no limit is imposed
func (Stack) CapReached ¶
CapReached returns a Boolean value indicative of whether the receiver has reached the maximum configured capacity.
func (Stack) Category ¶
Category returns the categorical label string value assigned to the receiver, if set, else a zero string.
Example ¶
var stk Stack = Basic().Push(1, 2, 3, 4) stk.SetCategory(`basic_stuff`) fmt.Printf("Category: %s", stk.Category())
Output: Category: basic_stuff
func (Stack) Defrag ¶
Defrag scans the receiver for breaks in the contiguity of slices and will collapse their formation so that they become contiguous. The effective ordering of repositioned slices is preserved.
For example, this:
"value1", nil, "value2", "value3", nil, nil, nil, "value4"
... would become ...
"value1", "value2", "value3", "value4"
Such fragmentation is rare and may only occur if the receiver were initially assembled with explicit nil instances specified as slices. This may also happen if the values were pointer references that have since been annihilated through some external means. This method exists for these reasons, as well as other corner-cases currently inconceivable.
The max integer, which defaults to fifty (50) when unset, shall result in the scan being terminated when the number of nil slices encountered consecutively reaches the maximum. This is to prevent the process from looping into eternity.
If run on a Stack or Stack type-alias that is currently in possession of one (1) or more nested Stack or Stack type-alias instances, Defrag shall hierarchically traverse the structure and process it no differently than the top-level instance. This applies to such Stack values nested with an instance of Condition or Condition type-alias as well.
This is potentially a destructive method and is still very much considered EXPERIMENTAL. While all tests yield expected results, those who use this method are advised to exercise extreme caution. The most obvious note of caution pertains to the volatility of index numbers, which shall shift according to the defragmentation's influence on the instance in question. By necessity, Len return values shall also change accordingly.
func (Stack) Delimiter ¶
Delimiter returns the delimiter string value currently set within the receiver instance.
Example ¶
This example demonstrates the creation of a list stack using comma delimitation and the retrieval of the same delimiter value.
// note: one could also use a rune // e.g: ',' or rune(44) for comma. L := List().SetDelimiter(`,`).Push( `item1`, `item2`, ) fmt.Printf("%s", L.Delimiter())
Output: ,
func (Stack) Encap ¶
Encap accepts input characters for use in controlled stack value encapsulation.
A single string value will be used for both L and R encapsulation.
An instance of []string with two (2) values will be used for L and R encapsulation using the first and second slice values respectively.
An instance of []string with only one (1) value is identical to the act of providing a single string value, in that both L and R will use one (1) value.
func (Stack) Err ¶
Err returns the error residing within the receiver, or nil if no error condition has been declared.
This method will be particularly useful for users who do not care for fluent-style operations and would instead prefer to operate in a more procedural fashion.
Note that a chained sequence of method calls of this type shall potentially obscure error conditions along the way, as each successive method may happily overwrite any error instance already present.
func (Stack) Fold ¶
Stack will fold the case of logical Boolean operators which are not represented through symbols. For example, `AND` becomes `and`, or vice versa. This won't have any effect on List-based receivers, or if symbols are used in place of said Boolean words.
A Boolean input value explicitly sets the bit as intended. Execution without a Boolean input value will *TOGGLE* the current state of the case-folding bit (i.e.: true->false and false->true)
func (Stack) ForwardIndices ¶
ForwardIndices will enable forward index support when using the Index method extended by this type. See the method documentation for further details.
A Boolean input value explicitly sets the bit as intended. Execution without a Boolean input value will *TOGGLE* the current state of the forward indices bit (i.e.: true->false and false->true)
Example ¶
var stk Stack = Basic().Push(1, 2, 3, 4) stk.ForwardIndices(true) slice, _ := stk.Index(1000) fmt.Printf("%d", slice.(int))
Output: 4
func (Stack) ID ¶
ID returns the assigned identifier string, if set, from within the underlying stack configuration.
func (Stack) Index ¶
Index returns the Nth slice within the given receiver alongside the true index number and a Boolean value indicative of a successful call of a non-nil value.
This method supports the use of the following index values depending on the configuration of the receiver.
Negatives: When negative index support is enabled, a negative index will not panic, rather the index number will be increased such that it becomes positive and within the bounds of the stack length, and (perhaps most importantly) aligned with the relative (intended) slice. To offer an example, -2 would return the second-to-last slice. When negative index support is NOT enabled, nil is returned for any index out of bounds along with a Boolean value of false, although no panic will occur.
Positives: When forward index support is enabled, an index greater than the length of the stack shall be reduced to the highest valid slice index. For example, if an index of twenty (20) were used on a stack instance of a length of ten (10), the index would transform to nine (9). When forward index support is NOT enabled, nil is returned for any index out of bounds along with a Boolean value of false, although no panic will occur.
In any scenario, a valid index within the bounds of the stack's length returns the intended slice along with Boolean value of true.
func (Stack) Insert ¶
Insert will insert value x to become the left index. For example, using zero (0) as left shall result in value x becoming the first slice within the receiver.
This method returns a Boolean value indicative of success. A value of true indicates the receiver length became longer by one (1).
This method does not currently respond to forward/negative index support. An integer value less than or equal to zero (0) shall become zero (0). An integer value that exceeds the length of the receiver shall become index len-1. A value that falls within the bounds of the receiver's current length is inserted as intended.
Use of the Insert method shall not result in fragmentation of the receiver instance, as any nil x value shall be discarded and not considered for insertion into the stack.
Example ¶
var stk Stack = Basic().Push(1, 2, 3, 5) add := 4 idx := 3 stk.Insert(add, idx) slice, _ := stk.Index(idx) fmt.Printf("%d", slice.(int))
Output: 4
func (Stack) IsEncap ¶
IsEncap returns a Boolean value indicative of whether value encapsulation characters have been set within the receiver.
func (Stack) IsFIFO ¶
IsFIFO returns a Boolean value indicative of whether the underlying receiver instance exhibits First-In-First-Out behavior as it pertains to the appending and truncation order of the receiver instance.
A value of false implies Last-In-Last-Out behavior, which is the default ordering scheme imposed upon instances of this type.
func (Stack) IsInit ¶
IsInit returns a Boolean value indicative of whether the receiver has been initialized using any of the following package-level functions:
- And
- Or
- Not
- List
- Basic
This method does not take into account the presence (or absence) of any user-provided values (e.g.: a length of zero (0)) can still return true.
func (Stack) IsNesting ¶
IsNesting returns a Boolean value indicative of whether at least one (1) slice member is either a Stack or Stack type alias. If true, this indicates the relevant slice descends into another hierarchical (nested) context.
func (Stack) IsPadded ¶
IsPadded returns a Boolean value indicative of whether the receiver pads its contents with a SPACE char (ASCII #32).
func (Stack) IsParen ¶
IsParen returns a Boolean value indicative of whether the receiver is parenthetical.
func (Stack) IsReadOnly ¶
IsReadOnly returns a Boolean value indicative of whether the receiver is set as read-only.
func (Stack) IsZero ¶
IsZero returns a Boolean value indicative of whether the receiver is nil, or uninitialized.
func (Stack) Kind ¶
Kind returns the string name of the type of receiver configuration.
Example ¶
var myStack Stack = And() fmt.Printf("Kind: '%s'", myStack.Kind())
Output: Kind: 'AND'
func (Stack) LeadOnce ¶
LeadOnce sets the lead-once bit within the receiver. This causes two (2) things to happen:
- Only use the configured operator once in a stack, and ...
- Only use said operator at the very beginning of the stack string value
Execution without a Boolean input value will *TOGGLE* the current state of the lead-once bit (i.e.: true->false and false->true)
Example ¶
This example demonstrates the LeadOnce feature, which limits a given Stack's logical operator usage to once-per, and only at the beginning (i.e.: the form of an LDAP Search Filter's operators when conditions are nested).
maker := func(r Stack) Stack { return r.Paren().LeadOnce().NoPadding() } Ands := maker(And().Symbol('&')) Ors := maker(Or().Symbol('|')).Push( Cond(`objectClass`, Eq, `engineeringLead`).NoPadding().Paren(), // OR condition #1 Cond(`objectClass`, Eq, `shareholder`).NoPadding().Paren(), // OR condition #1 ) // Begin filter at AND filter := Ands.Push( Cond(`objectClass`, Eq, `employee`).NoPadding().Paren(), // AND condition #1 Ors, // Begin OR (which is AND condition #2) ) fmt.Printf("%s", filter)
Output: (&(objectClass=employee)(|(objectClass=engineeringLead)(objectClass=shareholder)))
func (Stack) LogLevels ¶
LogLevels returns the string representation of a comma-delimited list of all active LogLevel values within the receiver.
func (Stack) Logger ¶
Logger returns the *log.Logger instance. This can be used for quick access to the log.Logger type's methods in a manner such as:
r.Logger().Fatalf("We died")
It is not recommended to modify the return instance for the purpose of disabling logging outright (see Stack.SetLogger method as well as the SetDefaultStackLogger package-level function for ways of doing this easily).
func (Stack) Mutex ¶
Mutex enables the receiver's mutual exclusion locking capabilities.
Subsequent calls of write-related methods, such as Push, Pop, Remove and others, shall invoke MuTeX locking at the latest possible state of processing, thereby minimizing the duration of a lock as much as possible.
func (Stack) NegativeIndices ¶
NegativeIndices will enable negative index support when using the Index method extended by this type. See the method documentation for further details.
A Boolean input value explicitly sets the bit as intended. Execution without a Boolean input value will *TOGGLE* the current state of the negative indices bit (i.e.: true->false and false->true)
Example ¶
var stk Stack = Basic().Push(1, 2, 3, 4) stk.NegativeIndices(true) slice, _ := stk.Index(-1) fmt.Printf("%d", slice.(int))
Output: 4
func (Stack) NoNesting ¶
NoNesting sets the no-nesting bit within the receiver. If set to true, the receiver shall ignore any Stack or Stack type alias instance when pushed using the Push method. In such a case, only primitives, Conditions, etc., shall be honored during the Push operation.
Note this will only have an effect when not using a custom PushPolicy. When using a custom PushPolicy, the user has total control -- and full responsibility -- in deciding what may or may not be pushed.
Also note that setting or unsetting this bit shall not, in any way, have an impact on pre-existing Stack or Stack type alias instances within the receiver. This bit only has an influence on the Push method and only when set to true.
A Boolean input value explicitly sets the bit as intended. Execution without a Boolean input value will *TOGGLE* the current state of the nesting bit (i.e.: true->false and false->true)
func (Stack) NoPadding ¶
NoPadding sets the no-space-padding bit within the receiver. String values within the receiver shall not be padded using a single space character (ASCII #32).
A Boolean input value explicitly sets the bit as intended. Execution without a Boolean input value will *TOGGLE* the current state of the padding bit (i.e.: true->false and false->true)
func (Stack) Paren ¶
Paren sets the string-encapsulation bit for parenthetical expression within the receiver. The receiver shall undergo parenthetical encapsulation ( (...) ) during the string representation process. Individual string values shall not be encapsulated in parenthesis, only the whole (current) stack.
A Boolean input value explicitly sets the bit as intended. Execution without a Boolean input value will *TOGGLE* the current state of the encapsulation bit (i.e.: true->false and false->true)
func (Stack) Pop ¶
Pop removes and returns the requisite slice value from the receiver instance. A Boolean value is returned alongside, indicative of whether an actual slice value was found.
The requisite slice shall be one (1) of the following, depending on ordering mode in effect:
- In the default mode -- LIFO -- this shall be the final slice (index "Stack.Len() - 1", or the "far right" element)
- In the alternative mode -- FIFO -- this shall be the first slice (index 0, or the "far left" element)
Note that if the receiver is in an invalid state, or has a zero length, nothing will be removed, and a meaningless value of true will be returned alongside a nil slice value.
Example (FIFO) ¶
b := Basic() b.SetFIFO(true) b.Push( float64(3.14159), float32(-9.378), -1, `banana`, ) popped, _ := b.Pop() fmt.Printf("%T, length now: %d", popped, b.Len())
Output: float64, length now: 3
Example (LIFO) ¶
b := Basic() b.Push( float64(3.14159), float32(-9.378), -1, `banana`, ) popped, _ := b.Pop() fmt.Printf("%T, length now: %d", popped, b.Len())
Output: string, length now: 3
func (Stack) Push ¶
Push appends the provided value(s) to the receiver, and returns the receiver in fluent form.
Note that if the receiver is in an invalid state, or if maximum capacity has been set and reached, each of the values intended for append shall be ignored.
func (Stack) ReadOnly ¶
ReadOnly sets the receiver bit 'ronly' to a positive state. This will prevent any writes to the receiver or its underlying configuration.
func (Stack) Remove ¶
Remove will remove and return the Nth slice from the index, along with a success-indicative Boolean value. A value of true indicates the receiver length became shorter by one (1).
Use of the Remove method shall not result in fragmentation of the stack: gaps resulting from the removal of slice instances shall immediately be "collapsed" using the subsequent slices available.
func (Stack) Replace ¶
Replace will overwrite slice idx using value x and returns a Boolean value indicative of success.
If slice i does not exist (e.g.: idx > receiver len), then nothing is altered and a false Boolean value is returned.
Use of the Replace method shall not result in fragmentation of the receiver instance; this method does not honor any attempt to replace any receiver slice value with nil.
func (Stack) Reset ¶
func (r Stack) Reset()
Reset will silently iterate and delete each slice found within the receiver, leaving it unpopulated but still retaining its active configuration. Nothing is returned.
func (Stack) Reveal ¶
Reveal processes the receiver instance and disenvelops needlessly enveloped Stack slices.
func (Stack) Reverse ¶ added in v1.0.1
Reverse shall re-order the receiver's current slices in a sequence that is the polar opposite of the original.
Example ¶
var c Stack = List().Push(0, 1, 2, 3, 4) fmt.Printf("%s", c.Reverse())
Output: 4 3 2 1 0
func (Stack) SetAuxiliary ¶
SetAuxiliary assigns aux, as initialized and optionally populated as needed by the user, to the receiver instance. The aux input value may be nil.
If no variadic input is provided, the default Auxiliary allocation shall occur.
Note that this method shall obliterate any instance that may already be present, regardless of the state of the input value aux.
Example ¶
// Always alloc stack somehow, in this // case just use List because its simple // and (unlike Basic) it is feature-rich. var list Stack = List() // alloc map aux := make(Auxiliary, 0) // populate map aux.Set(`somethingWeNeed`, struct { Type string Value []string }{ Type: `L`, Value: []string{ `abc`, `def`, }, }) // assign map to stack rcvr list.SetAuxiliary(aux) // verify presence call := list.Auxiliary() fmt.Printf("%T found, length:%d", call, call.Len())
Output: stackage.Auxiliary found, length:1
func (Stack) SetCategory ¶
SetCategory assigns the provided string to the stack's internal category value. This allows for a means of identifying a particular kind of stack in the midst of many.
Example ¶
var stk Stack = Basic().Push(1, 2, 3, 4) stk.SetCategory(`basic_stuff`) fmt.Printf("Category: %s", stk.Category())
Output: Category: basic_stuff
func (Stack) SetDelimiter ¶
SetDelimiter accepts input characters (as string, or a single rune) for use in controlled stack value joining when the underlying stack type is a LIST. In such a case, the input value shall be used for delimitation of all slice values during the string representation process.
A zero string, the NTBS (NULL) character -- ASCII #0 -- or nil, shall unset this value within the receiver.
If this method is executed using any other stack type, the operation has no effect. If using Boolean AND, OR or NOT stacks and a character delimiter is preferred over a Boolean WORD, see the Stack.Symbol method.
Example ¶
This example demonstrates the creation of a list stack using comma delimitation.
// note: one could also use a rune // e.g: ',' or rune(44) for comma. L := List().SetDelimiter(`+`).Push( `item1`, `item2`, ) fmt.Printf("%s", L)
Output: item1 + item2
func (Stack) SetErr ¶
SetErr sets the underlying error value within the receiver to the assigned input value err, whether nil or not.
This method may be most valuable to users who have chosen to extend this type by aliasing, and wish to control the handling of error conditions in another manner.
func (Stack) SetFIFO ¶
SetFIFO shall assign the bool instance to the underlying receiver configuration, declaring the nature of the append/truncate scheme to be honored.
- A value of true shall impose First-In-First-Out behavior
- A value of false (the default) shall impose Last-In-First-Out behavior
This setting shall impose no influence on any methods other than the Pop method. In other words, Push, Defrag, Remove, Replace, et al., will all operate in the same manner regardless.
Once set to the non-default value of true, this setting cannot be changed nor toggled ever again for this instance and shall not be subject to any override controls.
In short, once you go FIFO, you cannot go back.
func (Stack) SetID ¶
SetID assigns the provided string value (or lack thereof) to the receiver. This is optional, and is usually only needed in complex structures in which "labeling" certain components may be advantageous. It has no effect on an evaluation, nor should a name ever cause a validity check to fail.
If the string `_random` is provided, a 24-character alphanumeric string is randomly generated using math/rand and assigned as the ID.
Example (PointerAddress) ¶
var stk Stack = Basic().Push(1, 2, 3, 4) // can't predict what ID will be, // so we'll check the prefix to // be certain it begins with '0x'. stk.SetID(`_addr`) fmt.Printf("Address ID has '0x' prefix: %t", stk.ID()[:2] == `0x`)
Output: Address ID has '0x' prefix: true
Example (Random) ¶
var stk Stack = Basic().Push(1, 2, 3, 4) // can't predict what ID will // be, so we'll check length // which should always be 24. stk.SetID(`_random`) fmt.Printf("Random ID len: %d", len(stk.ID()))
Output: Random ID len: 24
func (Stack) SetLogLevel ¶
SetLogLevel enables the specified LogLevel instance(s), thereby instructing the logging subsystem to accept events for submission and transcription to the underlying logger.
Users may also sum the desired bit values manually, and cast the product as a LogLevel. For example, if STATE (4), DEBUG (8) and TRACE (32) logging were desired, entering LogLevel(44) would be the same as specifying LogLevel3, LogLevel4 and LogLevel6 in variadic fashion.
func (Stack) SetLogger ¶
SetLogger assigns the specified logging facility to the receiver instance.
Logging is available but is set to discard all events by default.
An active logging subsystem within the receiver supercedes the default package logger.
The following types/values are permitted:
- string: `none`, `off`, `null`, `discard` will turn logging off
- string: `stdout` will set basic STDOUT logging
- string: `stderr` will set basic STDERR logging
- int: 0 will turn logging off
- int: 1 will set basic STDOUT logging
- int: 2 will set basic STDERR logging
- *log.Logger: user-defined *log.Logger instance will be set; it should not be nil
Case is not significant in the string matching process.
Logging may also be set globally using the SetDefaultLogger package level function. Similar semantics apply.
func (Stack) SetPresentationPolicy ¶
func (r Stack) SetPresentationPolicy(ppol PresentationPolicy) Stack
SetPresentationPolicy assigns the provided PresentationPolicy closure function to the receiver, thereby enabling full control over the stringification of the receiver. Execution of this type's String() method will execute the provided policy instead of the package-provided routine.
Example ¶
This example demonstrates a custom user-authored stringer that assumes full responsibility for the string representation of a Stack instance.
// slices we intend to push // into our stack. slices := []any{ `safe_text`, `sensitive_text`, 1.261, `safe_text`, `sensitive_text`, []string{`health`, `your`, `for`, `bad`, `is`, `smoking`, `ziggurat`}, `irrelevant_text`, `sensitive_text`, `safe_text`, []string{`homes.`, `feelings,`, `your`, `about`, `talk`, `to`, `need`, `You`}, } // create a List stack, push the above slices // in variadic form and create/set a ppolicy. myStack := List() myStack.Push(slices...).SetPresentationPolicy(func(x ...any) string { var retval []string for i := 0; i < myStack.Len(); i++ { slice, _ := myStack.Index(i) switch tv := slice.(type) { case string: if tv == `safe_text` { retval = append(retval, tv+` (vetted)`) // declare safe } else if tv == `sensitive_text` { retval = append(retval, `[REDACTED]`) // redact } else { retval = append(retval, tv) // as-is } case []string: var message []string for j := len(tv); j > 0; j-- { message = append(message, tv[j-1]) } retval = append(retval, strings.Join(message, string(rune(32)))) default: retval = append(retval, fmt.Sprintf("%v (%T)", tv, tv)) } } // Since we're doing our own stringer, we can't rely on the // SetDelimiter method (nor any method used in the string // representation process). return strings.Join(retval, ` || `) }) fmt.Printf("%s", myStack)
Output: safe_text (vetted) || [REDACTED] || 1.261 (float64) || safe_text (vetted) || [REDACTED] || ziggurat smoking is bad for your health || irrelevant_text || [REDACTED] || safe_text (vetted) || You need to talk about your feelings, homes.
func (Stack) SetPushPolicy ¶
func (r Stack) SetPushPolicy(ppol PushPolicy) Stack
SetPushPolicy assigns the provided PushPolicy closure function to the receiver, thereby enabling protection against undesired appends to the Stack. The provided function shall be executed by the Push method for each individual item being added.
Example ¶
This example demonstrates the use of a custom PushPolicy instance assigned to the receiver instance to limit valid push candidates to only integers, and only those that are positive and are powers of two (n²).
Generally speaking, even though the input signature for instances of the PushPolicy type is variadic, it is recommended that it be used in a unary manner, as we will demonstrate by calling slice #0 explicitly and exclusively.
myStack := List() myStack.SetPushPolicy(func(x ...any) (err error) { if len(x) == 0 { return // no error because nothing was pushed } switch tv := x[0].(type) { case int: // We allow int values, but only certain // ones will be accepted for push. if tv <= 0 { // value cannot be negative nor can it be zero err = fmt.Errorf("%T->%T push denied: unsupported integer value: %d <= 0", tv, myStack, tv) } else if !isPowerOfTwo(tv) { // value must be power of two err = fmt.Errorf("%T->%T push denied: unsupported integer value: %d != n²", tv, myStack, tv) } default: // If not an integer, its most definitely bogus. err = fmt.Errorf("%T->%T push denied: unsupported type %T", tv, myStack, tv) } return }) // prepare some values to be pushed // into the myStack instance. values := []any{ 3.14159, 2, `2`, 14, nil, -81, uint8(3), 128, []int{1, 2, 3, 4}, 1023, 1, `peter`, nil, } // Push each slice individually and allow for the // opportunity to check for errors at each loop // iteration. Though this particular technique is // not required, it can be useful when dealing with // unvetted or unscrubbed data. var errct int for i := 0; i < len(values); i++ { myStack.Push(values[i]) // For the sake of a simple example, // let's just count the errors. Push // what we can, don't quit. if err := myStack.Err(); err != nil { errct++ } /* // Other error handling options for // the sake of a helpful example. One // or more of the actions below may // be appropriate, given the context // of the importing app ... if err := myStack.Err(); err != nil { //fmt.Println(err) //err = fmt.Errorf("Error with additional info prepended: %v", err) //panic(err) //return //continue or break //some other action } */tion } */ } fmt.Printf("Successful pushes: %d/%d", myStack.Len(), len(values))
Output: Successful pushes: 3/13
func (Stack) SetValidityPolicy ¶
func (r Stack) SetValidityPolicy(vpol ValidityPolicy) Stack
SetValidityPolicy assigns the provided ValidityPolicy closure function instance to the receiver, thereby allowing users to introduce inline verification checks of a Stack to better gauge its validity. The provided function shall be executed by the Valid method.
Example ¶
This example demonstrates the analytical capabilities made possible through use of the ValidityPolicy type.
Setting a scanning policy, as demonstrates below, can allow a more in-depth analysis of the receiver instance to occur.
The Stack.Valid method shall abandon its "vanilla checks" of the receiver and will, instead, report solely on the result of calling the specified user-authored ValidityPolicy.
// a custom type made by the user, // because why not? type demoStruct struct { Type string Value any } // Initialize our stack, and // push into it immediately. myStack := Basic().Push( `healthy stuff`, `healthy stuff`, `healthy stuff`, `healthy stuff`, demoStruct{ Type: `text`, Value: `complete_garbage`, }, ) // Set a ValidityPolicy. Users can handle // errors in any manner they wish, such as // using one the following actions: // // - wrap multiple errors in one // - encode error as JSON or some other encoding // - error filtering (e.g.: ignore all except X, Y and Z) // - craft preliminary error (e.g.: Found N errors; see logs for details) // // For the purpose of this simple example, we // are only scanning for demoStruct instances // and are only throwing an error should the // Value field not contain the literal string // of 'healthy stuff'. myStack.SetValidityPolicy(func(_ ...any) (err error) { // Iterate stack slices per length for i := 0; i < myStack.Len(); i++ { // Grab each stack index (slice) slice, _ := myStack.Index(i) // Perform type switch on slice switch tv := slice.(type) { case demoStruct: if tv.Type == `text` { if assert, _ := tv.Value.(string); assert != `healthy stuff` { // What a piece of junk! err = errorf("embedded instance is invalid") } } } // We choose not to go any // further when errors appear. if err != nil { break } } return }) // Execute Stack.Valid, which returns an error instance, // directly into a fmt.Printf call. fmt.Printf("%v", myStack.Valid())
Output: embedded instance is invalid
func (Stack) String ¶
String is a stringer method that returns the string representation of the receiver.
Note that invalid Stack instances, as well as basic Stacks, are not eligible for string representation.
func (Stack) Symbol ¶
Symbol sets the provided symbol expression, which will be a sequence of any characters desired, to represent various Boolean operators without relying on words such as "AND". If a non-zero sequence of characters is set, they will be used to supplant the default word-based operators within the given stack in which the symbol is configured.
Acceptable input types are string and rune.
Execution of this method with no arguments empty the symbol store within the receiver, thereby returning to the default word-based behavior.
This method has no effect on list-style stacks.
func (Stack) Transfer ¶
Transfer will iterate the receiver (r) and add all slices contained therein to the destination instance (dest).
The following circumstances will result in a false return:
- Capacity constraints are in-force within the destination instance, and the transfer request (if larger than the sum number of available slices) cannot proceed as a result
- The destination instance is nil, or has not been properly initialized
- The receiver instance (r) contains no slices to transfer
The receiver instance (r) is not modified in any way as a result of calling this method. If the receiver (source) should undergo a call to its Reset() method following a call to the Transfer method, only the source will be emptied, and of the slices that have since been transferred instance shall remain in the destination instance.
Example ¶
var source Stack = Basic().Push(1, 2, 3, 4) var dest Stack = Basic() source.Transfer(dest) slice, _ := dest.Index(2) fmt.Printf("%d", slice.(int))
Output: 3
func (Stack) Traverse ¶
Traverse will "walk" a structure of stack elements using the path indices provided. It returns the slice found at the final index, or nil, along with a success-indicative Boolean value.
The semantics of "traversability" are as follows:
- Any "nesting" instance must be a Stack or Stack type alias
- Condition instances must either be the final requested element, OR must contain a Stack or Stack type alias instance through which the traversal process may continue
- All other value types are returned as-is
If the traversal ended at any given value, it will be returned along with a positive ok value letting the user know they arrived at the coordinates they defined and that "something" was found.
If, however, any path elements remained and further traversal was NOT possible, the last slice is returned as nil.
As the return type is any, the slice value must be manually type asserted.
Example ¶
This example demonstrates traversing a Stack instance containing Condition slice instances. We use a path sequence of []int{1, 1} to target slice #1 on the first level, and value #1 of the second level.
// An optional Stack "maker" for configuring // a specific kind of Stack. Just looks neater // than doing fluent execs over and over ... sMaker := func(r Stack) Stack { // encapsulate in parens, use symbol rune // for logical operators only once, and // use no padding between kw, op and value return r.Paren().LeadOnce().NoPadding() } // An optional Condition "maker", same logic // as above ... cMaker := func(r Condition) Condition { // encapsulate in parens, no padding between // kw, op and value ... return r.Paren().NoPadding() } // Let's make a faux LDAP Search Filter ... // // This will be our top level, which is an AND Ands := sMaker(And().Symbol('&')) // This will be our second level Stack, which // is an OR containing a couple of Condition // instances in Equality form. Ors := sMaker(Or().Symbol('|')).Push( cMaker(Cond(`objectClass`, Eq, `engineeringLead`)), // OR condition #1 cMaker(Cond(`objectClass`, Eq, `shareholder`)), // OR condition #2 // **our traversal target** ) // Begin filter at AND, and push our // desired elements into the Stack. filter := Ands.Push( cMaker(Cond(`objectClass`, Eq, `employee`)), // AND condition #1 Ors, // Begin OR (which is AND's condition #2) ) // Bool returns shadowed only for brevity. // Generally you should not do that ... slice, _ := filter.Traverse(1, 1) // Enter coordinates condAssert, ok := slice.(Condition) // The return is any, so assert to what we expect if !ok { fmt.Printf("Type Assertion failed: %T is not expected value\n", slice) return } fmt.Printf("%s", condAssert) // use its String method automagically
Output: (objectClass=shareholder)
func (Stack) UnsetLogLevel ¶
UnsetLogLevel disables the specified LogLevel instance(s), thereby instructing the logging subsystem to discard events submitted for transcription to the underlying logger.
type ValidityPolicy ¶
ValidityPolicy is a first-class (closure) function signature that may be leveraged by users in order to better gauge the validity of a stack based on its configuration and/or values.
A ValidityPolicy function or method is executed via the Stack method Valid.