If the only tool you have is a hammer, then many different objects will seem like nails.
Mark Twain
Part 1 Introduction to SchemePart 2 Groove in the SchemePart 3 Practicing IronSchemeGet acquainted closer
It is time to learn the basic constructs of the Scheme language. The best way to learn how to use a new language is to start writing on it. Let's start a gradual immersion with the analysis of the most basic elements of the language.
')
I propose to run the IronScheme interpreter in REPL mode and enter the commands below.
A single line comment starts with a semicolon and is valid until the end of the line:
A Scheme program consists of lists enclosed in parentheses and separated by a space (s-expression). The function call is written as (fxyz ...), where f is the name of the function, and x, y, z, ... are operands.
(+ 2 2)
Here we have performed the operation of adding two numbers.
Expressions can be nested:
(+ 2 (+ 1 1))
Thus, expressions can consist of atoms or other expressions. In the example above, the numbers “1” and “2” are atoms, and “(+ 2 (+ 1 1))” and “(+ 1 1)” expressions.
Primitives
Numbers:
9999999999999999999999
To create a list of any values, for example, from the same primitives, use the list function, whose arguments will be put together in a list. You can do it another way, to suppress the calculation. Suppression is achieved by the quote function or its sugar equivalent by a single quote in front of the “'” list. It is important to remember that list does not suppress calculations.
(list 1 2 3 4 5 (+ 1 2 3))
Some arithmetic operations
(+ 1 1)
Boolean algebra
To indicate the truth there is a primitive “#t”, a lie is designated as “#f”, besides all other values other than “#f” are interpreted as true:
(not #t)
Characters, lines
According to the RnRs standard, symbols can be represented in the code in two ways, by a symbol that designates itself or by a symbol code:
#\A
Strings are arrays of characters of fixed length and are enclosed in double quotes:
"Hello, world!"
Quotes inside a string can be escaped with a backslash:
"Benjamin \"Bugsy\" Siegel"
To print a string to standard output, you can use the display function that accepts a string as an argument:
(display "Some string")
Strings can be combined:
(string-append "Hello " "world!")
You can access the character of a string by index as follows:
(string-ref "Apple" 0)
For formatting strings, it is convenient to use the formatting function:
(format "~a can be ~a" "strings" "formatted")
To prevent the result of formatting from being lost, you can assign a string to a variable:
(define str (format "~a can be ~a" "strings" "formatted"))
Variables
You can declare variables using the define function, in which the first argument is the name of the function, the second is not a necessary argument, the value by which the variable will be initialized. A variable name can contain any characters except: () [] {} ”, '`; # / \
For example:
(define some-var 5) some-var
Variables in Lisp without strong typing and can point to atoms or functions.
The “set!” Operation saves the value in a variable, in fact, is an analogue of the assignment operator “=” from other languages. Do not forget to first declare a variable operation «define»:
(define my-name "unknown") my-name
Attempting to access a previously undeclared variable will cause an exception.
It is convenient to immediately declare a group of local variables using the construct (let ...).
(let ( (a "My") (b "name") (c "is") (d "Bob") ) (set! d "Sara") (format "~a ~a ~a ~a" abcd) )
Functions
To create a function, a construction is used (lambda (abc) body), where a, b, c are arguments, body is a sequence of commands.
(lambda () "Hello World") (lambda (x) (+ xx))
The function created above does not have a name, so it is not possible to access it. To access the created function, you can assign it to a variable.
(define hello-world (lambda () "Hello World")) (hello-world)
Or so:
(define hello-world) (set! Hello-world (lambda () "Hello World")) (hello-world)
A more convenient construction is usually used (define (function-name arg1 arg2) body)
(define (mul ab) (* ab)) (mul 2 3)
The function always returns the last value.
(define (last-string) “one” “two” “three”) (last-string)
Flow control
For branching in Scheme, there are various constructions of the most familiar, but not always the most convenient, if-then-else type
(if #t
If a branch needs to execute several commands in a row, then they should be enclosed in the “begin” block.
(if (< 1 3) (begin (display “one line”) (newline) (display “two line”) (- 1 3) ) )
When you need to check several conditions, the cond design is convenient.
(cond ((> 2 2) "wrong!") ((< 2 2) "wrong again!") ((= 2 2) "ok") (else "wrong also") )
If the code needs to be executed only in the case of truth, “when” is perfect
(when (< 1 3) “true”)
There are two ways to organize a cycle: recursion
(define (lp i) (when (< i 10) (display (format "i=~a\n" i)) (lp (+ 1 i)) ) ) (lp 5)
Or using a named "let"
(let loop ((i 0))
Macros
Scheme macros are quite a powerful tool that allows you to extend the syntax of the language by creating new constructs. However, you should not get too carried away and apply macros only where it is really necessary. Macro definition begins with the define-syntax command
(define-syntax macro (syntax-rules (<keywords>) ((<pattern>) <template>) ... ((<pattern>) <template>) ) )
<keywords> - Keywords that can be used in the template description. For example, you can write a macro for the construct “(forech (item in items) ...)”, in this case the key word is “in”, which must be present.
<pattern> - A template that describes what is entered at the macro.
<template> - A template describing what should be transformed In the macro, the ellipsis "..." means that the body can contain one or more forms.
Consider using macros to create while and for loops.
(define-syntax while (syntax-rules () ((while condition body ...) (let loop () (when condition body ... (loop) ) ) ) ) )
check the created macro
(define iter 0) (while (< iter 10) (set! iter (+ iter 1)) (displayln iter ))
Define a macro for a for loop:
(define-syntax for (syntax-rules () ((for (iterator from to) body ...) (let loop((iterator from)) (when (< iterator to) body ... (loop (+ 1 iterator)) ) ) ) ) )
Check:
(for (i 0 15) (displayln i))
Exceptions
In life, it is not very rare to have the need to use unstable code, which during execution can cause an exception. In Lisp and Scheme in particular, there is an advanced exception handling system, below is a simple example of how you can handle exceptions without fear that the program will crash.
(guard (cond
We learned some of the fundamentals of the Scheme language described by the standard. Of course, this article does not provide all the possibilities of the language, otherwise the article would have turned out to be too voluminous, in fact it would be a translation of the standard. However, what we have learned is quite enough to develop practically useful applications on Scheme.