More
So far we have covered a majority of the various aspects of Auto that you will use. In this chapter, we will cover some more aspects that will make our knowledge of Auto more well-rounded.
Since Auto transpiles to Python, we will also highlight features that are available in Python but work differently (or are not available) in Auto. These sections are marked with a "Note for Python Programmers" callout.
Tuple Unpacking
Ever wished you could return two different values from a function? In Auto, you can do this using tuples. A tuple is a sequence of values grouped together, and you can "unpack" them into separate variables.
Save as tuple_swap.auto:
Output:
$ auto run tuple_swap.auto
Before: a=5, b=8
After: a=8, b=5
x=10, y=20
Error 2: detailsHow It Works
The get_error_details function returns a tuple (2, "details"). We can then unpack this tuple into separate variables using the let (error_num, error_msg) = ... syntax. This is called tuple destructuring.
Note that Auto uses let for variable declarations, so we cannot simply reassign a and b with let. Instead, we use a temporary variable to swap values. In Auto, once a variable is declared with let, it can be reassigned without let.
Note for Python Programmers:
In Python, the fastest way to swap two variables is
a, b = b, a, which leverages tuple packing and unpacking in a single statement. Auto does not support this shorthand syntax, so you must use a temporary variable for swapping.
Special Methods
There are certain methods such as init and drop which have special significance in Auto types. Python uses "dunder" methods (methods with double underscores, like __init__ and __str__) to customize class behavior. Auto takes a different approach with named methods that are more readable.
Save as special_methods.auto:
Output:
$ auto run special_methods.auto
Student(Alice, 20)
Student(Bob, 22)How It Works
In Auto, we define a to_string method on our Student type to provide a human-readable string representation. This is called explicitly with .to_string().
In Python, the __str__ method is called automatically by print() and str(). Python also supports many other special methods such as __lt__ (for the < operator), __getitem__ (for indexing), and __len__ (for the len() function).
Note for Python Programmers:
Python uses "dunder" methods (
__str__,__lt__,__getitem__,__len__, etc.) to customize class behavior. Auto does not use dunder methods. Instead:
__init__becomesfn init(&self, ...)__str__becomesfn to_string(&self) -> str(called explicitly)__lt__and other comparison operators are not directly supported as method overloads in Auto__getitem__and__len__are not supported as method overloads in AutoAuto's approach prioritizes explicit method calls over operator overloading, making code easier to read and understand.
Lambda Functions
A lambda in Python is a way to create small, anonymous function objects. Lambda takes a parameter followed by a single expression, and that expression becomes the body of the function.
Auto does not have lambda expressions. Instead, Auto encourages you to use named functions, which are more readable and easier to debug.
Save as lambda.auto:
Output:
$ auto run lambda.auto
[{'y': 1, 'x': 4}, {'y': 3, 'x': 2}]How It Works
In the Python version, we use lambda i: i["y"] to create an anonymous function that extracts the "y" value from each dictionary. This lambda is passed as the key argument to the sort method.
In the Auto version, we use an inline anonymous function expression fn(item) { item["y"] } instead. While this is slightly more verbose than Python's lambda, it is more explicit and readable. Auto can also define a named helper function (like compare_y in the example) when the logic is more complex.
Note for Python Programmers:
Python's
lambdacreates anonymous functions limited to a single expression. Auto usesfn(params) { body }for anonymous function expressions, which supports multiple statements. For simple cases, Auto also supports passing named function references directly.
List Comprehensions
List comprehensions are a Python feature used to derive a new list from an existing list. They provide a concise way to apply transformations and filters in a single expression.
Auto does not have list comprehensions. Instead, Auto uses standard for loops, which are more explicit and easier to read, especially for complex transformations.
Save as list_comp.auto:
Output:
$ auto run list_comp.auto
[6, 8]How It Works
The Python version uses a list comprehension [2 * i for i in list_one if i > 2] to create a new list. This single expression reads as: "for each item in list_one, if the item is greater than 2, multiply it by 2 and add it to the new list."
The Auto version achieves the same result using a for loop. We declare an empty list list_two, iterate over list_one, check the condition with an if statement, and append the transformed values. While this requires more lines of code, each step is clear and explicit.
Note for Python Programmers:
Python list comprehensions like
[expr for x in iterable if condition]have no direct equivalent in Auto. Useforloops withifconditions and.append()instead. While slightly more verbose, Auto's approach is equally efficient and arguably more readable for beginners.
Decorators
Decorators in Python are a shortcut for applying wrapper functions. They use the @decorator_name syntax to "wrap" a function with additional behavior, such as logging, retrying, or access control.
Auto does not have a @decorator syntax. Instead, Auto achieves the same effect through explicit function composition -- you simply call the wrapper function and pass the original function as an argument.
Save as decorator.auto:
Output:
$ auto run decorator.auto
Saving: hello
Saving: hello
Saving: helloHow It Works
In the Python version, the @retry decorator wraps the save_to_database function. When save_to_database is called, the retry wrapper intercepts the call, and if an exception is raised, it retries up to 5 times with increasing delays.
In the Auto version, we achieve the same pattern by explicitly calling with_retry(save_to_database), which returns a new function safe_save. This new function wraps the original with retry logic. The result is functionally equivalent, just more explicit.
Note for Python Programmers:
Python's
@decoratorsyntax is syntactic sugar forfunction = decorator(function). Auto does not support this syntax. To achieve the same effect in Auto, call the wrapper function explicitly:let wrapped = wrapper(original_fn). The concept of higher-order functions (functions that take or return other functions) is the same in both languages.
The assert Statement
The assert statement is used to assert that something is true. For example, if you are very sure that you will have at least one element in a list you are using and want to check this, the assert statement is ideal. When the assert statement fails, an AssertionError is raised.
Since Auto transpiles to Python, the assert statement works identically in both languages.
>>> let mylist = ["item"]
>>> assert mylist.len() >= 1
>>> mylist.pop()
'item'
>>> assert mylist.len() >= 1
Traceback (most recent call last):
...
AssertionErrorThe assert statement should be used judiciously. Most of the time, it is better to catch exceptions, either handle the problem or display an error message to the user and then quit.
Note for Python Programmers:
The
assertstatement works the same way in Auto as in Python. Auto usesmylist.len()instead of Python'slen(mylist), andmylist.pop()is a method call in both languages.
Summary
We have covered some more features in this chapter:
- Tuple unpacking -- returning and destructuring multiple values from functions
- Special methods -- how Auto's named methods (
init,to_string) differ from Python's dunder methods (__init__,__str__) - Lambda functions -- Auto uses named functions or inline
fnexpressions instead of Python'slambda - List comprehensions -- Auto uses
forloops instead of Python's concise list comprehension syntax - Decorators -- Auto uses explicit function composition instead of Python's
@decoratorsyntax - The
assertstatement -- works the same in both Auto and Python
While Auto does not support some of Python's more advanced syntactic sugar, it provides clear, readable alternatives that achieve the same results. The trade-off is slightly more verbose code in exchange for greater clarity and consistency.