Skip to content

Commit

Permalink
add additional functions
Browse files Browse the repository at this point in the history
  • Loading branch information
ryanwaits committed Aug 10, 2024
1 parent c1de38c commit 34cb96c
Show file tree
Hide file tree
Showing 65 changed files with 5,248 additions and 0 deletions.
85 changes: 85 additions & 0 deletions content/docs/stacks/clarity/functions/if.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
---
title: if
description: Conditional evaluation in Clarity smart contracts.
---

## Function Signature

```clarity
(if bool expr1 expr2)
```

- Input:
- `bool`: A boolean expression
- `expr1`: An expression to evaluate if `bool` is true
- `expr2`: An expression to evaluate if `bool` is false
- Output: The result of `expr1` if `bool` is true, otherwise the result of `expr2`

## Why it matters

The `if` function is crucial for:

1. Implementing conditional logic in smart contracts.
2. Making decisions based on dynamic conditions.
3. Controlling the flow of contract execution.
4. Simplifying complex logic by branching based on conditions.

## When to use it

Use `if` when you need to:

- Execute different code paths based on a condition.
- Implement logic that depends on the state or input values.
- Control the flow of your contract based on dynamic conditions.
- Simplify complex decision-making processes.

## Best Practices

- Ensure that both `expr1` and `expr2` return the same type.
- Use clear and meaningful boolean expressions for readability.
- Avoid deeply nested `if` statements for better maintainability.
- Combine with other control flow functions like `match` for more complex logic.

## Practical Example: Conditional Token Transfer

```clarity
(define-map userBalances { userId: principal } { balance: uint })
(define-public (transfer-tokens (amount uint) (recipient principal))
(let
(
(senderBalance (default-to u0 (map-get? userBalances { userId: tx-sender })))
)
(if (>= senderBalance amount)
(begin
(map-set userBalances { userId: tx-sender } { balance: (- senderBalance amount) })
(map-set userBalances { userId: recipient } { balance: (+ (default-to u0 (map-get? userBalances { userId: recipient })) amount) })
(ok true)
)
(err u1)
)
)
)
```

This example demonstrates:
1. Using `if` to check if the sender has sufficient balance before transferring tokens.
2. Executing different code paths based on the result of the balance check.
3. Handling both the success and failure cases appropriately.

## Common Pitfalls

1. Forgetting that both `expr1` and `expr2` must return the same type.
2. Using overly complex boolean expressions, making the code hard to read.
3. Not handling all possible conditions, leading to unexpected behavior.
4. Overusing `if` for logic that could be simplified with other control flow functions.

## Related Functions

- `match`: Used for pattern matching and handling multiple conditions.
- `and`: Logical AND operator for combining boolean expressions.
- `or`: Logical OR operator for combining boolean expressions.

## Conclusion

The `if` function is a fundamental tool for implementing conditional logic in Clarity smart contracts. It allows developers to control the flow of contract execution based on dynamic conditions, enabling more complex and responsive contract behavior. When used effectively, `if` simplifies decision-making processes and enhances the readability and maintainability of your smart contract code.
99 changes: 99 additions & 0 deletions content/docs/stacks/clarity/functions/impl-trait.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
---
title: impl-trait
description: Implementing traits in Clarity smart contracts.
---

## Function Signature

```clarity
(impl-trait trait-name)
```

- Input:
- `trait-name`: The name of the trait to implement
- Output: Not applicable

## Why it matters

The `impl-trait` function is crucial for:

1. Enabling contracts to conform to specific interfaces.
2. Allowing dynamic function calls between contracts.
3. Promoting code reuse and modularity in smart contract development.
4. Ensuring contracts adhere to predefined behaviors and standards.

## When to use it

Use `impl-trait` when you need to:

- Implement a predefined interface in your contract.
- Allow other contracts to interact with your contract through a common interface.
- Ensure your contract adheres to specific standards or behaviors.
- Enable dynamic function calls using `contract-call?`.

## Best Practices

- Define traits at the top level of your contract for clarity and organization.
- Ensure all required functions in the trait are implemented in your contract.
- Use meaningful and descriptive names for traits and their functions.
- Document the purpose and usage of each trait in your contract.

## Practical Example: Implementing a Token Trait

Let's define a simple token trait and implement it in a contract:

```clarity
(define-trait token-trait
(
(transfer (principal principal uint) (response bool uint))
(get-balance (principal) (response uint uint))
)
)
(impl-trait token-trait)
(define-map balances { user: principal } { balance: uint })
(define-public (transfer (sender principal) (recipient principal) (amount uint))
(let
(
(senderBalance (default-to u0 (map-get? balances { user: sender })))
(recipientBalance (default-to u0 (map-get? balances { user: recipient })))
)
(if (>= senderBalance amount)
(begin
(map-set balances { user: sender } { balance: (- senderBalance amount) })
(map-set balances { user: recipient } { balance: (+ recipientBalance amount) })
(ok true)
)
(err u1)
)
)
)
(define-read-only (get-balance (user principal))
(ok (default-to u0 (map-get? balances { user: user })))
)
```

This example demonstrates:
1. Defining a `token-trait` with `transfer` and `get-balance` functions.
2. Implementing the `token-trait` in a contract using `impl-trait`.
3. Providing implementations for the `transfer` and `get-balance` functions.

## Common Pitfalls

1. Forgetting to implement all required functions in the trait, leading to deployment errors.
2. Using inconsistent function signatures between the trait and the implementation.
3. Not documenting the purpose and usage of traits, making the contract harder to understand.
4. Overlooking the need for proper error handling in trait functions.

## Related Functions

- `define-trait`: Used to define a new trait.
- `contract-call?`: Used to call functions dynamically on contracts that implement a trait.
- `define-public`: Used to define public functions that can be called from outside the contract.

## Conclusion

The `impl-trait` function is a powerful tool for promoting modularity and code reuse in Clarity smart contracts. By implementing predefined interfaces, contracts can interact dynamically and adhere to specific standards and behaviors. When used effectively, `impl-trait` enhances the flexibility and maintainability of your smart contract code, enabling more robust and interoperable decentralized applications.
74 changes: 74 additions & 0 deletions content/docs/stacks/clarity/functions/index-of.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
---
title: index-of
description: Finding the index of an element in a list in Clarity smart contracts.
---

## Function Signature

```clarity
(index-of list element)
```

- Input:
- `list`: A list of elements
- `element`: The element to find in the list
- Output: `(optional uint)`

## Why it matters

The `index-of` function is crucial for:

1. Locating the position of an element within a list.
2. Implementing search functionality in smart contracts.
3. Enabling conditional logic based on the presence and position of elements.
4. Simplifying list operations by providing a built-in search mechanism.

## When to use it

Use `index-of` when you need to:

- Determine the position of an element in a list.
- Check if an element exists in a list and retrieve its index.
- Implement logic that depends on the order or position of elements.
- Simplify list search operations without writing custom loops.

## Best Practices

- Ensure the list and element types are compatible.
- Handle the `none` case when the element is not found in the list.
- Use meaningful variable names for better readability.
- Consider the performance implications when searching large lists.

## Practical Example: Finding an Element in a List

Let's implement a function that finds the index of a given element in a list of integers:

```clarity
(define-read-only (find-index (element int) (numbers (list 10 int)))
(index-of numbers element))
;; Usage
(find-index 3 (list 1 2 3 4 5)) ;; Returns (some u2)
(find-index 6 (list 1 2 3 4 5)) ;; Returns none
```

This example demonstrates:
1. Using `index-of` to find the position of an element in a list.
2. Handling both the case where the element is found and where it is not found.

## Common Pitfalls

1. Assuming the element will always be found, leading to unhandled `none` cases.
2. Using `index-of` on lists with incompatible element types.
3. Overlooking the performance impact of searching very large lists.
4. Not considering that `index-of` returns a 0-based index.

## Related Functions

- `filter`: Used to create a new list containing only elements that match a condition.
- `map`: Applies a function to each element in a list, transforming the elements.
- `len`: Returns the length of a list.

## Conclusion

The `index-of` function is a powerful tool for locating elements within lists in Clarity smart contracts. It provides a straightforward way to search for elements and retrieve their positions, enabling more complex list operations and conditional logic. When used effectively, `index-of` simplifies list search operations and enhances the readability and maintainability of your smart contract code.
82 changes: 82 additions & 0 deletions content/docs/stacks/clarity/functions/int-to-ascii.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
---
title: int-to-ascii
description: Converting integers to ASCII string representations in Clarity smart contracts.
---

## Function Signature

```clarity
(int-to-ascii value)
```

- Input: `int | uint`
- Output: `(string-ascii 40)`

## Why it matters

The `int-to-ascii` function is crucial for:

1. Converting integer values to their string representations.
2. Facilitating the display and logging of numeric data.
3. Enabling the use of numeric values in contexts that require strings.
4. Simplifying the process of creating human-readable outputs from numeric data.

## When to use it

Use `int-to-ascii` when you need to:

- Convert an integer or unsigned integer to a string.
- Display numeric values in a human-readable format.
- Log or store numeric data as strings.
- Prepare numeric data for concatenation with other strings.

## Best Practices

- Ensure the integer value is within the range that can be represented as a string.
- Use meaningful variable names for better readability.
- Combine with other string functions for more complex string manipulations.
- Be aware of the maximum length of the resulting string (40 characters).

## Practical Example: Logging a User's Balance

Let's implement a function that logs a user's balance as a string:

```clarity
(define-map userBalances { userId: principal } { balance: uint })
(define-public (log-balance (user principal))
(let
(
(balance (default-to u0 (map-get? userBalances { userId: user })))
(balanceStr (int-to-ascii balance))
)
(print balanceStr)
)
)
;; Usage
(map-set userBalances { userId: tx-sender } { balance: u100 })
(log-balance tx-sender) ;; Logs "100"
```

This example demonstrates:
1. Using `int-to-ascii` to convert a user's balance to a string.
2. Logging the string representation of the balance using `print`.
3. Handling the case where the user has no balance set.

## Common Pitfalls

1. Assuming the resulting string will always fit within 40 characters.
2. Forgetting to handle cases where the integer value is not set or is zero.
3. Using `int-to-ascii` in performance-critical sections without considering the overhead.
4. Not combining with other string functions for more complex manipulations.

## Related Functions

- `print`: Used to log or display string values.
- `concat`: Used to concatenate multiple strings.
- `default-to`: Used to provide default values for optional types.

## Conclusion

The `int-to-ascii` function is a powerful tool for converting integer values to their string representations in Clarity smart contracts. It enables developers to create human-readable outputs from numeric data, facilitating logging, display, and storage of numeric values as strings. When used effectively, `int-to-ascii` enhances the readability and usability of numeric data within your smart contract code.
Loading

0 comments on commit 34cb96c

Please sign in to comment.