Язык программирования Snek

*Язык встраиваемых вычислений, вдохновленный Python.

Кит Паккард

Версия v1.9, 2022-12-20

 ~

Оглавление

Лицензия

Благодарности

  1. История и мотивы

    1. Arduino в программе Lego
    2. Новый язык
    3. Представляем Snek
  2. Нежный самоучитель Snek

    1. Hello World
    2. Переменные
    3. Функции
    4. Простая арифметика
    5. Циклы, диапазоны и печать двух значений
    6. Списки и кортежи
    7. Словари
    8. While
    9. If
    10. Управление GPIO

Справочное руководство Snek

  1. Лексическая структура

    1. Числа
    2. Имена
    3. Ключевые слова
    4. Пунктуация
    5. Белое пространство(Пробелы и новые строки)
    6. Строковые константы
    7. Константы списков и кортежей
    8. Константы словаря
  2. Типы данных

    1. Списки и кортежи
  3. Операторы

    1. Слайсы
    2. Интерполяция строк
  4. Выражения и присваивания

  5. Поток управления

    1. if
    2. while
    3. for
    4. return value
    5. break
    6. продолжить
    7. pass
  6. Другие утверждения

    1. import name
    2. global name [ , name ... ]
    3. del location
    4. assert value
  7. Функции

    1. def
  8. Стандартные встроенные функции

    1. len(value)
    2. print( value1, value2, ..., end='\n').
    3. sys.stdout.flush()
    4. ord( string)
    5. chr( число)
    6. abs( число)
    7. math.sqrt( число).
  9. Общие системные функции

    1. exit( value)
    2. time.sleep( seconds)
    3. time.monotonic()
    4. random.seed( seed)
    5. random.randrange( max).
  10. Функции ввода

    1. float( value)
    2. input( prompt)
  11. Математические функции

    1. Теоретико-числовые функции и функции представления
    2. Силовые и логарифмические функции
    3. Тригонометрические функции
    4. Угловое преобразование
    5. Гиперболические функции
    6. Специальные функции
    7. Математические константы
  12. Функции GPIO

    1. talkto( pin)
    2. setpower( power)
    3. setleft()
    4. setright()
    5. on()
    6. off()
    7. onfor( секунды)
    8. read( pin)
    9. pullnone( pin)
    10. pullup( pin)
    11. pulldown( pin)
    12. stopall()
    13. neopixel( пиксели)
    14. tone( частота)
    15. tonefor( частота, секунды)
    16. Константы музыкальных нот
  13. Встроенные функции EEPROM

    1. eeprom.write()
    2. eeprom.show()
    3. eeprom.load()
    4. eeprom.erase()
    5. reset()
  14. Функция преобразования температуры

    1. температура( значение датчика)
  15. Встроенные функции Curses

    1. curses.initscr()
    2. curses.endwin()
    3. curses.noecho(), curses.echo(), curses.cbreak(), curses.nocbreak()
    4. stdscr.nodelay( nodelay)
    5. stdscr.erase()
    6. stdscr.addstr( строка, столбец, строка)
    7. stdscr.move( строка, столбец)
    8. stdscr.refresh()
    9. stdscr.getch()
  16. Среда разработки Snek

    1. Запуск SnekDE
    2. Основная навигация
    3. Подключение к устройству
    4. Получение и размещение программ на устройстве
    5. Загрузка и сохранение программ на хост

 ~

Лицензия

Авторское право © 2019 Кит Паккард

Этот документ выпущен на условиях Стандартной общественной лицензии GNU, версия 3 или более поздняя.

https://www.gnu.org/licenses/gpl-3.0.en.html

 ~

Благодарности

Спасибо Джейн Кенни-Норберг за создание программы научно-технического образования с использованием Lego. Джейн преподавала моим детям науку в начальной школе и Lego после школы, и разрешала мне тоже приходить и играть. Я все еще помогаю и преподаю, хотя мои дети уже почти закончили бакалавриат.

Спасибо Кристоферу Рики и Генри Гиллеспи, которые являются студентами и преподавателями в программе Джейн и помогают обучать программированию Arduino с помощью роботов Lego. Кристофер также помогал разрабатывать и тестировать Snek.

Кит Паккард keithp@keithp.com https://keithp.com

 ~

Глава 1. История и мотивы

Обучение компьютерному программированию школьников в возрасте 10-14 лет сопряжено с некоторыми интересными проблемами. Графические языки, которые создают программы из элементов, перетаскиваемых с помощью мыши или сенсорной панели, могут быть удручающе медленными. Пользователи этих языков не развивают навыки переноса, необходимые для более сложных языков. Сложные языки, такие как C, Java и даже Python, настолько велики, что перегружают новичка богатой семантикой, такой как "объекты" и другие конструкции программирования более высокого уровня.

В давно минувшие дни начинающим программистам обычно предлагали микрокомпьютеры, на которых работали очень маленькие языки: BASIC, Forth, Logo и тому подобное. Эти языки были ограничены не для того, чтобы помочь студенту, а потому что компьютеры, на которых они работали, были маленькими.

Сегодня вводное программирование преподается в огромном диапазоне сред, от встроенных систем до облачных систем. Многие из них являются технологическими тупиками - закрытыми системами, которые не дают возможности даже извлечь исходный код, не говоря уже о том, чтобы повторно использовать его в другой среде.

Некоторые системы, такие как Raspberry PI и Arduino, являются открытыми - они используют стандартные языки, так что навыки, полученные на них, могут быть полезны в других местах. Хотя самые маленькие из этих машин по объему памяти и процессора похожи на те ранние микрокомпьютеры, они программируются как встраиваемые компьютеры с помощью полного компилятора C++, работающего на отдельном настольном компьютере или ноутбуке.

 ~

1.1. Arduino в программе Lego

Я ввел системы Arduino в класс около пяти лет назад. Оборудование было потрясающим, и мы построили несколько забавных роботов. Спустя несколько лет я создал индивидуальное оборудование Arduino для наших нужд. Наше оборудование имеет винтовые клеммы для входов и выходов, батарейный блок на задней панели и сильноточные контроллеры двигателей для анимации роботов. Поскольку эти платформы являются Arduino \ (с процессором ATmega 328P и USB-последовательным преобразователем FTDI), мы можем использовать стандартные средства разработки Arduino.

Студенты боролись со сложным синтаксисом языка Arduino C: им было особенно трудно набирать непонятные знаки препинания и не забывать ставить точки с запятой. Я часто слышал комментарии типа "это занимает слишком много времени" и "почему он так придирчив к точкам с запятой?". Отсутствие интерактивного режима делало эксперименты немного медленнее, чем на наших системах Logo. Несмотря на трудности, были ученики, которые сделали интересные проекты по робототехнике на Arduino:

 ~

Оборудование было именно таким, как мы хотели, и несколько учеников в дальнейшем использовали навыки, полученные в программе. Однако программное обеспечение не было рассчитано на молодых студентов, только начинающих писать код. Вместо того чтобы выбрасывать существующие системы и начинать все сначала, я подумал, не можем ли мы продолжать использовать то же самое оборудование, но улучшить среду программирования.

 ~

1.2. Новый язык

Я искал крошечный язык программирования, который мог бы работать на Arduino и предлагать опыт, более похожий на Lego Logo. Я хотел что-то, что студенты могли бы использовать в качестве основы для дальнейшего компьютерного образования и изучения, что-то очень похожее на Python.

Существует уменьшенная версия Python, называемая MicroPython: это все еще довольно большой язык, занимающий несколько сотен кБ в ПЗУ и значительный объем оперативной памяти. Язык также достаточно велик, чтобы мы не смогли подробно рассмотреть его за время занятий.

В итоге я решил просто попытаться написать небольшой язык, вдохновленный Python, который мог бы поместиться на нашем существующем оборудовании, совместимом с Arduino Duemilanove. Эта машина имеет:

Я считаю, что сокращение языка до небольшого подмножества Python позволит языку работать на этом оборудовании и в то же время будет достаточно простым, чтобы ознакомить студентов со всем языком за небольшое количество учебного времени.

 ~

1.3. Знакомство с Snek

Целями языка Snek являются:

Snek вдохновлен Python, но это не Python. Можно писать программы на Snek, которые работают под управлением полноценной системы Python, но большинство программ на Python не будут работать под Snek.

 ~

Глава 2. Нежный учебник по Snek

Прежде чем мы перейдем к деталям языка, давайте сделаем паузу и просто немного изучим язык, чтобы получить представление о том, как он работает. Мы не будем ничего подробно описывать и не будем изучать все тонкости. Мы надеемся создать основу для этих деталей.

В этом учебнике показано, что появляется на экране - как то, что вводит пользователь, так и то, что отображает Snek. Пользовательский ввод показан жирным шрифтом, как здесь в строках, которые начинаются с > или +. В остальных строках вывод Snek отображается *жирным шрифтом, как здесь.

 ~

2.1. Hello World

Традиционное упражнение для любого нового языка - заставить его вывести на консоль слова hello, world. Поскольку Snek предлагает интерактивную командную строку, мы можем сделать это несколькими способами.

Первый способ - использовать Snek для эхо-отклика на то, что вы вводите. Запустите Snek на своем компьютере

(возможно, найдя Snek в системном меню или набрав snek в обычной командной строке). При первом запуске Snek представится и будет ждать, пока вы что-нибудь напечатаете.

Добро пожаловать в Snek версии v1.9
> 

В этой подсказке Snek будет печатать все, что вы напечатаете:

> 'hello, world'
'hello, world'

Здесь мы видим, что строки Snek можно заключать в одинарные кавычки. Строки также могут быть заключены в двойные кавычки, что может быть полезно, если вы хотите включить в них одинарные кавычки. Snek всегда печатает строки, используя одинарные кавычки, поэтому вывод здесь будет таким же, как и раньше.

> "hello, world"
'hello, world'

На самом деле Snek делает нечто более сложное, чем эхо того, что вы вводите. То, что вы вводите, называется "выражением", а Snek берет это выражение, вычисляет значение, которое оно представляет, и выводит его на печать. В данном случае значением выражения 'hello, world' или 'hello, world' является 'hello, world'.

Вместо того чтобы вводить привет, мир напрямую, мы можем написать более сложное выражение, которое его вычислит:

> 'hello,' + ' world'
'hello, world'

На данном этапе мы используем функцию интерактивной среды, которая печатает значение введенных выражений. Попробуем вместо этого использовать функцию print:

> print('hello, world')
привет, мир

На этот раз Snek вывел строку без кавычек. Это потому, что функция print выводит именно то, что ей было задано, без кавычек, в то время как командный процессор печатает значения в том же формате, в котором они появятся в программе(где вам понадобятся кавычки).

Вам может быть интересно, куда выводится значение, полученное в результате оценки выражения print('hello, world'). Ведь Snek печатал значение других выражений. Ответ заключается в том, что функция print оценивает "нет значения", и когда Snek видит "нет значения", он ничего не печатает. Мы увидим это еще несколько раз в процессе обучения.

 ~

2.2. Переменные

Переменные - это способ запоминания Snek'а. У каждой переменной есть имя, например, мох или дерево, и каждая переменная может хранить одно значение. Вы задаете\(или "присваиваете") значение переменной с помощью оператора =, и получаете значение, используя имя в другом месте:

> moss = 'hello, world'
> moss
'hello, world'

Snek создает переменную всякий раз, когда вы впервые присваиваете ей значение.

 ~

2.3. Функции

Давайте определим функцию, которая использует print для печати hello world и вызовем ее. Чтобы определить новую функцию в Snek, мы используем ключевое слово def следующим образом:

> def hello():
+     print('hello, world')
+
> hello()
hello, world

Здесь происходит много всего интересного. Во-первых, мы видим, как объявить функцию с помощью ключевого слова def, за которым следует имя функции, а затем "аргументы" в круглых скобках. Об аргументах мы поговорим в следующем разделе "Простая арифметика". А пока просто напечатайте (). После аргументов стоит двоеточие.

Двоеточия появляются в нескольких местах в Snek и (вне словарей) используются одинаково. После двоеточия Snek ожидает увидеть список утверждений. Обычный способ включения списка утверждений - напечатать их по одному на строке, отступив от строки, содержащей двоеточие, на несколько пробелов. Количество пробелов не имеет значения, но каждая строка должна иметь одинаковый отступ. Когда вы закончите со списком утверждений, вы введете строку со старым уровнем отступа.

При вводе списка утверждений командный процессор будет выдавать запрос + вместо >, чтобы дать вам понять, что он еще ждет ввода, прежде чем что-либо сделать. Пустая строка завершает список утверждений для функции hello и возвращает вас к обычному командному интерпретатору.

Наконец, мы вызываем новую функцию hello и смотрим результаты.

Snek обычно завершает каждую операцию печати переходом к следующей строке.

Это потому, что функция print имеет именованный параметр под названием end, который по умолчанию устанавливается на новую строку ('\\n'). Вы можете изменить его на любой другой, как, например:

> def hello():
+ print('hello', end=',')
+ print('world', end='\n')
+
> hello()
hello, world

Первый вызов добавляет a к выводу, тогда как второй вызов явно добавляет символ новой строки, заставляя вывод перейти на следующую строку. Есть несколько символов, которые используют эту нотацию обратной косой черты; они описаны в разделе "Строковые константы".

 ~

2.4. Простая арифметика

Давайте напишем функцию для преобразования температуры по Фаренгейту в температуру по Цельсию. Если вы помните, это:

      °C = (5 / 9)(°F - 32)

Snek не может использовать знак ° в именах переменных, поэтому мы будем использовать только C и F:

> # Преобразование из градусов Фаренгейта в градусы Цельсия
> def f_to_c(F):
+ return (5/9)*(F-32)
+
> f_to_c(38)
3.333333

Символ # вводит комментарий, который продолжается до конца строки. Все, что находится внутри комментария, игнорируется Snek.

Функция f_to_c принимает один "аргумент" под названием F. Внутри функции F - это переменная, которая устанавливается в значение, помещенное внутрь круглых скобок при вызове f_to_c. В этом примере мы вызываем f_to_c со значением 38. Snek получает значение 38 из F всякий раз, когда Snek находит его в функции:

+ return (5/9) * (F - 32)
⇒
      return (5/9) * (38 - 32)
⇒
      return 3.333333

Snek требует явного оператора умножения, *, так как он не понимает математическую конвенцию, согласно которой соседние значения должны перемножаться. Оператор return - это способ сообщить Snek, что данная функция вычисляет значение, которое должно быть возвращено вызывающей стороне.

Числа в Snek могут быть записаны с использованием _ в качестве разделителя, что особенно полезно при записи больших чисел.

> # вы можете написать
> c = 299_792_458
> # и Snek интерпретирует это как
> c = 299792458

 ~

2.5. Циклы, диапазоны и печать двух значений

Теперь, когда у нас есть функция для выполнения этого преобразования, мы можем вывести удобную справочную таблицу для автономного использования:

> # Печать удобной таблицы преобразования (K&R???)*.
> def f_to_c_table():
+ for F in range(0, 100, 10):
+ C = f_to_c(F)
+ print('%fF = %fC ' % (F, C))
+
> f_to_c_table()
 0.000000F = -17.777779C
10.000000F = -12.222223C
20.000000F = -6.666667C 
30.000000F = -1.111111C
40.000000F = 4.444445C
50.000000F = 10.000000C
60.000000F = 15.555556C
70.000000F = 21.111113C
80.000000F = 26.666668C
90.000000F = 32.222225C

Здесь мы видим новый оператор: оператор for. Оно проходит по диапазону значений, присваивая управляющую переменную (F, в данном случае) каждому из значений в диапазоне, а затем оценивая список утверждений внутри него.

Функция range создает список значений для F, начиная с первого значения и делая шаг непосредственно перед вторым значением. Если вы дадите range только два аргумента, Snek будет делать шаг на 1. Если вы дадите range только один аргумент, Snek будет использовать 0 в качестве начальной точки.

Нам нужно вставить числовые значения в строку, отображаемую print. Во многих языках для этого используется специальная функция форматированной печати. В Snek есть более универсальный механизм, называемый "интерполяцией строк". Интерполяция строк использует оператор %. Snek обходит строку слева и вставляет значения из списка значений, заключенных в круглые скобки, справа везде, где за символом % следует символ. Результатом интерполяции строк является другая строка, которая затем передается в print, который выводит ее на экран.

Форматирование значений зависит от символа, следующего за знаком %; это обсуждается в разделе Интерполяция строк. Как сделать набор значений справа, обсуждается в следующем разделе "Списки и кортежи".

 ~

2.6. Списки и кортежи

Списки и кортежи в Snek являются тесно связанными типами данных. Оба они представляют упорядоченный набор объектов.

Единственное различие заключается в том, что списки могут быть изменены после создания, а кортежи - нет. Мы называем списки "мутабельными", а кортежи - "неизменяемыми". Списки вводятся как объекты, разделенные запятыми и заключенные в квадратные скобки, а кортежи - как объекты, разделенные запятыми и заключенные в круглые скобки:

> ['hello,', ' world']
['hello,', ' world']
> ('hello,', ' world')
('hello,', ' world')

Давайте присвоим их переменным, чтобы мы могли изучить их более подробно:

> l = [ 'hello,', ' world' ]
> t = ( 'hello,', ' world' )

Как упоминалось ранее, списки и кортежи упорядочены. Это означает, что на каждый элемент списка или кортежа можно ссылаться по номеру. Это число называется индексом элемента, в Snek индексы начинаются с 0:

> l[0]
'hello,'
> t[1]
' world'

Списки могут быть изменены, кортежи - нет:

> l[0] = 'goodbye,'
> l
[ 'goodbye,', ' world' ]
> t[0] = 'beautiful'
<stdin>:5 invalid type: ('hello,', ' world')

Последний вывод - это сообщение Snek о том, что значение ('hello', ' world') не может быть изменено.

Мы можем использовать другую форму оператора for для перебора значений в списке или кортеже:

> def print_list(list):
+ for e in list:
+ print(e)
+
> print_list(l)
goodbye, 
world
> print_list(t)
hello,
world

Подобно форме, описанной в разделе "Циклы, диапазоны и печать двух значений", этот оператор for присваивает управляющую переменную (e в данном случае) каждому из элементов списка по очереди и оценивает утверждения внутри него.

Списки и кортежи могут быть конкатенированы(объединены в одно целое) с помощью оператора +:

> ['hello,'] + ['world']
['hello,', ' world']

Кортежи из одного элемента имеют немного странный синтаксис, чтобы отличить их от выражений, заключенных в круглые скобки: за значением внутри кортежа следует запятая:

> ( 'hello' , ) + ( 'world' , )
('hello', 'world')

 ~

2.7. Словари

Словари - это самая причудливая структура данных в Snek. Подобно спискам и кортежам, словари хранят множество значений. В отличие от списков и кортежей, словари не индексируются по числам. Вместо этого словари индексируются по другому значению Snek. Единственное требование - чтобы значение индекса было неизменяемым, чтобы оно никогда не могло измениться. Списки и словари - единственные изменяемые структуры данных в Snek: все остальное может быть использовано в качестве индекса словаря.

Индексирующее значение в словаре называется "ключ", а индексируемое значение - "значение". Словари вводятся путем заключения пар ключ/значение, разделенных запятыми, в фигурные скобки:

> { 1:2, 'hello,' : ' world' }
{ 'hello,': 'world', 1:2 }

Обратите внимание, что Snek переупорядочил наш словарь. Это потому, что словари всегда хранятся в отсортированном порядке, и эта сортировка включает тип ключей. Словари могут содержать только один элемент с заданным ключом: вы можете задавать словари с дублирующимися ключами, но в результирующем словаре будет только последнее значение.

Давайте присвоим наш словарь переменной и немного поиграем с ним:

> d = { 1:2, 'hello,' : ' world' }
> d[1]
2
> d['hello,']
' world'
> d[1] = 3
> d['goodnight'] = 'moon'
> d
{ 'goodnight':'moon', 'hello,':'world', 1:3 }
> d[56]
<stdin>:7 недопустимое значение: 56

В этом примере показано создание словаря и присвоение ему значения d, затем получение элементов словаря и присвоение новых значений. Вы можете добавлять элементы в словарь, используя индекс, которого еще нет. При запросе элемента, которого нет, выдается сообщение об ошибке.

Вы также можете перебирать ключи в словаре, используя тот же синтаксис for, который использовался выше. Давайте попробуем нашу функцию print_list на d:

> print_list(d)
goodnight
hello,
1

Вы можете проверить, находится ли элемент в словаре, используя оператор in:

> if 1 in d:
+ print('yup')
+ else:
+ print('nope')
+
yup
> if 56 in d:
+ print('yup')
+ else:
+ print('nope')
+
nope

 ~

2.8. while

Оператор for полезен при итерации по диапазону значений. Иногда мы хотим использовать более общий поток управления. Мы можем переписать нашу программу пересчета температуры с помощью цикла while следующим образом:

> def f_to_c_table():
+ F = 0
+ while F < 100:
+ C = f_to_c(F)
+ print('%fF = %fC' % (F, C))
+ F = F + 10
+
> f_to_c_table()
 0.000000F = -17.777779C
10.000000F = -12.222223C
20.000000F = -6.666667C
30.000000F = -1.111111C
40.000000F = 4.444445C
50.000000F = 10.000000C
60.000000F = 15.555556C
70.000000F = 21.111113C
80.000000F = 26.666668C
90.000000F = 32.222225C

Это делает то же самое, что и цикл for в разделе "Циклы, диапазоны и печать двух значений": сначала он присваивает F значение 0, а затем перебирает утверждения до тех пор, пока F не станет меньше 100.

 ~

2.9. if

Операторы If позволяют выбрать один из многих путей выполнения. Каждому блоку операторов предшествует выражение: если выражение оценивается как True, то выполняются следующие операторы. В противном случае выполняется следующий тест, пока не будет достигнут конец if. Вот функция, которая измеряет, сколько в строке букв верхнего регистра, букв нижнего регистра и цифр:

> def count_chars(s):
+     d = 0
+     l = 0
+     u = 0
+     o = 0
+     for c in s:
+         if '0' <= c and c <= '9':
+             d += 1
+         elif 'a' <= c and c <= 'z':
+             l += 1
+         elif 'A' <= c and c <= 'Z':
+             u += 1
+         else:
+             o += 1
+     print('digits %d" % d)
+     print('lower %d" % l)
+     print('upper %d" % u)
+     print('other %d" % o)
+
> count_chars('4 Score and 7 Years Ago')
digits 2
lower 13
upper 3
other 5

Операторы elif пробуют другие альтернативы, если предыдущие тесты if не сработали. Оператор else выполняется, если все предыдущие тесты if и elif не сработали.

Этот пример также вводит оператор сравнения less-than-or-equal <= и демонстрирует, что for v in a также работает со строками.

 ~

2.10. Управление GPIO

Пины ввода-вывода общего назначения, или "GPIO", - это пины встроенного процессора, которыми может управлять программа, запущенная на этом процессоре.

Когда Snek работает на встроенных устройствах, таких как Duemilanove или Metro M0 Express, он предоставляет функции для прямого управления этими GPIO пинами. Вы можете использовать любое из этих или любое другое устройство, которое использует стандартные номера выводов Arduino, для этих примеров.

 ~

2.10.1. Включение встроенного светодиода

Давайте начнем с включения светодиода, который обычно доступен на цифровом выводе 13:

> talkto(D13)
> on()

Давайте сделаем немного фантастичнее и замигаем:

> talkto(D13)
> while True:
+ onfor(.5)
+ time.sleep(.5)

 ~

2.10.2. Подключение цифрового входа

Найдите кусок провода, чтобы соединить цифровой контакт 1 с GND, и давайте управлять светодиодом с помощью этого примитивного переключателя:

> talkto(D13)
> while True:
+ if read(D1):
+ on()
+ else:
+ off()

Когда провод подключен, светодиод выключается, а когда провод не подключен, светодиод включается. Именно так работают простые переключатели на Arduino.

Snek многократно считывает входные данные и устанавливает светодиод так быстро, как только может. Это происходит тысячи раз в секунду, создавая иллюзию, что светодиод меняется в тот момент, когда меняется переключатель.

 ~

2.10.3. Использование аналогового входа

Если у вас есть датчик освещенности или потенциометр, вы можете подключить его к аналоговому выводу 0 и заставить светодиод следить за датчиком:

> talkto(D13)
> while True:
+ onfor(1-read(A0))
+ time.sleep(1-read(A0))

 ~

2.10.4. Управление двигателями

До сих пор мы говорили только об использовании одного пина за раз. Контроллеры двигателей Arduino используют два пина: один для питания и один для направления. Snek позволяет вам сообщить ему оба пина одновременно, а затем предоставляет отдельные функции для установки питания и направления. Если к вашей плате подключен контроллер двигателя с выводом 3 в качестве питания и выводом 2 в качестве направления, вы можете запустить двигатель на половину мощности и заставить его менять направление с помощью следующих функций:

> talkto((3,2))
> setpower(0.5)
> on()
> while True:
+ setleft()
+ time.sleep(1)
+ setright()
+ time.sleep(1)

 ~

Справочное руководство Snek

Остальная часть этой книги представляет собой справочное руководство по языку Snek, включая встроенные функции и среду разработки Snek.

 ~

Глава 3. Лексическая структура

Программы Snek разбиваются лексером на последовательность лексем. Последовательность лексем распознается синтаксическим анализатором.

 ~

3.1. Числа

Snek поддерживает 32-битные числа с плавающей точкой и понимает обычный формат чисел с плавающей точкой:

<целое число>< дробь><экспонента>
123.456e+12

integer.

Непустая последовательность десятичных цифр

дробь

Десятичная точка (период), за которой следует возможно пустая последовательность десятичных цифр

экспонента

Буква 'e' или 'E', за которой следует необязательный знак и непустая последовательность цифр, указывающая величину экспоненты.

Все части необязательны, хотя число должно содержать хотя бы одну цифру в целой или дробной части.

Значения с плавающей запятой (представленные внутри IEEE 854 в 32-битном формате) варьируются примерно от

от -1.70141e+38 до 1.70141e+38. Имеется 1 бит знака, 8 бит экспоненты и 23 хранимых/24 эффективных бита значащего числа (часто называемого мантиссой). Существует два значения бесконечности (положительное и отрицательное) и значение "Не число" (NaN), указывающее на то.

Вычисления с использованием целочисленных значений будут выдавать ошибку для значений, которые не могут быть представлены как 24-битное целое число. К ним относятся слишком большие значения и значения с дробными компонентами.

 ~

3.2. Имена

Имена в Snek используются для обозначения переменных, как глобальных, так и локальных для конкретной функции. Имена состоят из начальной буквы или знака подчеркивания, за которым следует последовательность букв, цифр, знаков подчеркивания и точки. Вот некоторые допустимые имена:

привет
_hello
_h4
math.sqrt

А вот некоторые недопустимые имена:

.hello
4square

 ~

3.3. Ключевые слова

Ключевые слова выглядят как обычные имена Snek, но они обрабатываются языком особым образом и поэтому не могут быть использованы в качестве имен. Вот список ключевых слов Snek:

и assert break continue
def del elif else
for global if import
in is not or
pass range return while

 ~

3.4. Пунктуация

Snek использует множество специальных символов, чтобы сделать программы более читабельными; отделяя имена и ключевые слова от операторов и другого синтаксиса.

: ; , ( ) [ ] {
}    + - * ** / // %
& | ~ ^ << >> = +=
-= *= **= /= //= %= &= |=
~= ^= <<= >>= > != < <=
== >= >

 ~

3.5. Белое пространство (Пробелы и новые строки)

Snek использует отступы для идентификации структуры программы. Snek не разрешает использовать табуляцию для отступов; табуляция является недопустимым символом в программах Snek. Высказывания в одном блоке (список высказываний) имеют одинаковый отступ; высказывания в более глубоких блоках имеют больший отступ, в более мелких - меньший.

Когда Snek набирает текст непосредственно в подсказке Snek, пустые строки становятся существенными, так как Snek не может знать, что вы напечатаете дальше. Вы можете увидеть это в учебнике, где Snek заканчивает блок с отступом на пустой строке.

При загрузке Snek из файла пустые строки(и строки, содержащие только комментарий) полностью игнорируются; отступ этих строк не влияет на уровень отступа блока. В этом случае имеют значение только строки с маркерами Snek.

Пробелы в середине строки имеют значение только в том случае, если они необходимы для разделения лексем; в других местах вы можете вставлять их сколько угодно много или мало.

 ~

3.6. Строковые константы

Строковые константы в Snek заключаются в одинарные или двойные кавычки. Используйте одинарные кавычки, чтобы легко включить в строку двойные кавычки, и наоборот. Строки не могут занимать несколько строк, но вы можете ввести несколько строк, расположенных рядом друг с другом, и в программе они будут объединены в одну строковую константу.

\n -- Новая строка. Переход к первому столбцу следующей строки.

\r -- Возврат каретки. Переход к первому столбцу текущей строки.

\t -- Табуляция. Переход к следующей "остановке табуляции" в выводе. Обычно это следующий столбец, кратный 8 в текущей строке.

\xdd -- Шестнадцатеричное значение. Используйте две шестнадцатеричные цифры для обозначения любого символа.

\\ - Обратная косая черта. Используйте две обратные косые черты во входных данных, чтобы получить одну обратную косую черту в строковой константе.

Все остальное, что следует за обратной косой чертой, является только этим символом. В частности:

\" -- Буквальная двойная кавычка. Используется внутри строк с двойными кавычками.

\' -- Буквальная одинарная кавычка. Используется внутри строк с одинарными кавычками.

 ~

3.7. Константы списков и кортежей

Константы списков и кортежей в Snek - это значения, разделенные запятыми и заключенные в скобки: квадратные скобки для списков, круглые скобки для кортежей.

Вот некоторые допустимые списки:

['hello', 'world'].
Глава 3. Лексическая структура 21
Стандартная общественная лицензия GNU версии 3 или более поздней
21
[12]

Вот некоторые допустимые кортежи:

(1, 2, 3)
('hello', 'world')
(12,)

Обратите внимание на последний случай - чтобы отличить значение в круглых скобках от кортежа с одним значением, кортеж должен иметь запятую в конце. Только кортежи с одним значением представляются с запятой в конце.

 ~

3.8. Константы словаря

Словари в Snek представляют собой пары ключ/значение, разделенные запятыми и заключенные в фигурные скобки. Ключи отделяются от значений двоеточием.

Вот некоторые допустимые словари:

{ 1:2, 3:4 }
{ 'pi' : 3.14, 'e' : 2.72 }
{ 1: 'один' }

Вы можете включать записи с дублирующимися ключами: результирующий словарь будет содержать только последнюю запись. В остальном порядок записей не имеет значения: результирующий словарь всегда будет одинаковым:

> { 1:2, 3:4 } == { 3:4, 1:2 }
1

Когда Snek печатает словари, они всегда печатаются в одном и том же порядке, поэтому два одинаковых словаря будут иметь одинаковое строковое представление.

 ~

Глава 4. Типы данных

Как и в Python, в Snek нет объявления типов. Вместо этого, каждое значение имеет собственное представление - любая переменная может содержать значение с любым представлением. Для того чтобы все было достаточно просто, Snek имеет только несколько типов представления:

Числа.

Вместо того, чтобы иметь целые числа и значения с плавающей точкой, Snek представляет числа с плавающей точкой, как описано ранее. Целочисленные значения менее 24 бит могут быть представлены именно в этих значениях с плавающей точкой: программы, требующие точного поведения целых чисел, могут работать до тех пор, пока значения могут храниться в 24 битах.

Строки

Строки - это просто списки байтов. Snek не имеет встроенной поддержки кодировок. Поскольку это просто списки байтов, вы можете спокойно хранить в них значения UTF-8. Только не ожидайте, что индексирование будет возвращать кодовые точки Юникода.

Списки

Списки - это упорядоченные коллекции значений. Вы можете изменять содержимое списка, добавляя или удаляя элементы. В других языках такие списки часто называют массивами или векторами. Списки - это "изменяемые" значения.

Кортежи

Кортежи - это неизменяемые списки значений. Вы не можете изменить сам кортеж после его создания. Если какой-либо элемент кортежа является изменяемым, вы можете изменить этот элемент и увидеть измененные результаты в кортеже.

Словари

Словари

Словарь - это связка между ключами и значениями. Они работают подобно спискам, поскольку в них можно хранить и извлекать значения. Индексом в словаре может быть любое неизменяемое значение, то есть любое значение, отличное от списка, словаря или кортежа, содержащего список или словарь. Словари - это "изменяемые" значения.

 ~

Функции

Функции - это значения в Snek. Вы можете хранить их в переменных или списках, а затем извлекать их позже.

Булево

Как и в Python, в Snek нет явного типа Boolean. Вместо этого, различные значения работают в булевом контексте как True или False. Все ненулевые числа, непустые строки / списки / кортежи / словари и все функции являются истинными. Нулевые, пустые строки / списки / кортежи / словари являются ложными. Имя True - это просто другой способ напечатать число 1. Аналогично, имя False - это просто другой способ ввода числа 0.

 ~

4.1. Списки и кортежи

Оператор += работает со списками несколько иначе, чем с любым другим типом - он добавляет список к существующему, а не создает новый список. Это видно из следующего примера:

> a = [1, 2]
> b = a
> a += [3]
> b
[1, 2, 3]

Сравните это с кортежами, к которым (поскольку они неизменяемы) нельзя добавлять значения. В этом примере b сохраняет исходное значение кортежа. a получает новый кортеж, состоящий из (3,), добавленный к исходному значению.

> a = (1,2)
> b = a
> a += (3,)
> b
(1, 2)
> a
(1, 2, 3)

 ~

Глава 5. Операторы

Операторы - это такие вещи, как + или -. Они являются частью грамматики языка и служат для того, чтобы сделать программы более читабельными, чем если бы все было вызовом функции. Как и в Python, поведение операторов Snek часто зависит от значений, над которыми они работают. Snek включает в себя большинство операторов Python. Некоторые числовые операции работают со значениями с плавающей точкой, другие - с целочисленными значениями. Операторы, которые работают только с целочисленными значениями, преобразуют значения с плавающей точкой в целые числа, а затем берут целочисленный результат и преобразуют его обратно в значение с плавающей точкой.

значение + значение

Оператор Plus выполняет сложение чисел или конкатенацию строк, списков и кортежей.

значение - значение

Оператор Minus выполняет вычитание чисел.

значение * значение.

Оператор умножения выполняет умножение чисел. Если вы умножите строку 's' на число 'n', вы получите 'n' копий 's', конкатенированных вместе.

значение / значение

Оператор Divide выполняет деление на числа.

значение // значение

Оператор Div выполняет "целочисленное деление" на числа, получая результат такой, что x // y == floor(x / y) для всех чисел x и y.

значение % значение

Оператор Modulus дает "остаток после деления" своих аргументов, такой что

x == y * (x // y) + x % y

для всех чисел x и y. Если левый операнд является строкой, то выполняется "интерполяция" либо с одним значением, либо со списком/кортежем значений и используется для создания форматированного вывода. Подробности см. в разделе Интерполяция строк.

значение ** значение

Оператор Power выполняет экспоненцию чисел.

значение & значение

Оператор Binary And выполняет побитовое И над целыми числами.

value | value

Оператор Binary Or выполняет побитовое ИЛИ над целыми числами.

значение ^ значение.

Двоичный оператор Xor выполняет побитовое XOR для целых чисел.

value << value.

Оператор Left Shift выполняет побитовый сдвиг влево для целых чисел.

value >> value

Оператор Right Shift выполняет побитовый сдвиг влево для целых чисел.

not value

Булевский оператор Not выдает True, если его аргумент равен False, и False в противном случае. То есть, если операнд - одно из истинных значений, то Not возвращает False (что равно 0), а если операнд - ложное значение, то Not возвращает True (что равно 1).

a и b

Булевский оператор And сначала оценивает a. Если это значение False, то возвращается его значение. В противном случае возвращается значение b.

a или b.

Булевский оператор And сначала оценивает a. Если это True, то возвращается его значение. В противном случае возвращается значение b.

a is b

Истинно, если a и b являются одним и тем же объектом.

a is not b

Истинно, если a и b не являются одним и тем же объектом.

a in b

Истинно, если a содержится в b. Для строк это означает, что a является подстрокой b. Если b - кортеж или список, это означает, что a является одним из элементов b. Если b - словарь, это означает, что a является одним из ключей b.

a не в b

Это то же самое, что не (a в b).

~ значение.

Оператор Binary Not выполняет побитовую операцию NOT над своим целочисленным операндом.

- value

При использовании в качестве унарного префиксного оператора, унарный оператор Minus выполняет отрицание чисел.

+ значение

При использовании в качестве унарного префиксного оператора унарный оператор плюс не делает с числом ничего.

value [ index ]

Оператор index выбирает index-ый член строк, списков, кортежей и словарей.

`[ value [ , value ... ]]

Оператор List создает новый List с указанными членами. Обратите внимание, что List с одним значением не имеет запятой после значения и отличается от оператора Index только тем, как он появляется во входных данных.

( значение )

Круглые скобки служат для контроля порядка вычислений в выражениях. Значения внутри круглых скобок вычисляются до того, как они используются в качестве значений для других операторов.

( значение , ) или ( значение [ , значение ... ])

Оператор Tuple создает новый кортеж с указанными членами. Кортеж с одним значением нуждается в запятой, чтобы его можно было отличить от выражения, заключенного в круглые скобки.

{ key : value [ , key : value ... ] }

Оператор Dictionary создает новый словарь с заданными парами ключ/значение. Все ключи должны быть неизменяемыми.

 ~

5.1. Слайсы

Оператор Slice, value [ base : bound : stride ], извлекает последовательность значений из строк, списков и кортежей. Он создает новый объект с указанным подмножеством значений из оригинала. Новый объект соответствует типу исходного.

база

Первый элемент значения, выбранный для среза. Если base отрицательна, то отсчет ведется не от начала, а от конца value.

bound

Первый элемент значения за пределами диапазона, выбранного для среза.

stride

Расстояние между выбранными элементами. Stride может быть отрицательным, в этом случае элементы выбираются в обратном порядке, начиная с конца значения и двигаясь к началу. Ошибкой является то, что stride равно нулю.

Все три значения являются необязательными. Значение по умолчанию для stride равно единице. Если stride положительно, то значение по умолчанию для base равно 0, а значение по умолчанию для bound равно длине массива. Если stride отрицательный, то значением по умолчанию для base будет индекс последнего элемента в value (что равно len(value) - 1), а значением по умолчанию для bound будет -1. Кусочек с одним двоеточием воспринимается как указание на базу и границу. Вот несколько примеров:

> # initialize a to a
> # Кортеж символов
> a = ('a', 'b', 'c', 'd', 'e', 'f')
> # При всех значениях по умолчанию a[:] выглядит
> # так же, как a
> a[:]
('a', 'b', 'c', 'd', 'e', 'f')
> # Переверните кортеж
> a[::-1]
('f', 'e', 'd', 'c', 'b', 'a')
> # Выберите конец кортежа, начинающийся
> # с индекса 3
> a[3:]
('d', 'e', 'f')
> # Выберите начало кортежа,
> # заканчивающегося до индекса 3
> a[:3]
('a', 'b', 'c')

 ~

5.2. Интерполяция строк

Интерполяцию строк в Snek можно спутать с форматированной печатью в других языках. В Snek функция print печатает любые аргументы в том виде, в котором они заданы, разделяя их пробелами на строке. Интерполяция строк создает новую строку из строки спецификации формата и списка или кортежа параметров: эта новая строка может быть использована для печати или для чего-либо другого, для чего может понадобиться строка.

Если требуется только одно значение, его не нужно заключать в список или кортеж. Следует помнить, что если это единственное значение само является кортежем или списком, то интерполяция строки даст неверный ответ.

Внутри спецификации формата String есть спецификаторы преобразования, которые указывают, куда вставлять значения из параметров. Они обозначаются знаком %, за которым следует один символ: этот символ является индикатором формата и указывает, как форматировать значение. Первый спецификатор преобразования использует первый элемент из параметров и т.д. Символами индикатора формата являются:

%d

%i

%o

%x

%X

Форматирует число как целое число, отбрасывая любую дробную часть и без экспоненты. %d и %i представляют значение по основанию 10. %o использует основание 8 (восьмеричное), а %x и %X - основание 16 (шестнадцатеричное), причем %x использует строчные буквы (a-f), а %X - прописные буквы (A-F).

%e

%E

%f

%F

%g

%G

Форматирование числа с плавающей запятой. В верхнем регистре используется E для разделителя экспонент, в нижнем регистре - e, в остальном они идентичны. %e всегда использует экспоненциальную нотацию, %f никогда не использует экспоненциальную нотацию. %g использует ту нотацию, которая делает вывод меньше.

%c

Вывод одного символа. Если значение параметра - число, оно преобразуется в символ. Если параметр является строкой, то используется первый символ из строки.

%s

Вывод строки. При этом не вставляются кавычки или обратные слэши.

%r

Генерирует печатное представление любого значения, аналогично тому, как это значение было бы представлено в программе Snek.

Если значение параметра не соответствует требованиям индикатора формата, или если в качестве индикатора формата используется любой другой символ, то вместо него будет использован %r.

Вот несколько примеров интерполяции строк:

> print('hello %s' % 'world')
привет мир
> print('hello %r' % 'world')
hello 'world'
> print('pi = %d' % 3.1415)
pi = 3
> print('pi = %f' % 3.1415)
pi = 3.141500
> print('pi = %e' % 3.1415)
pi = 3.141500e+00
> print('pi = %g' % 3.1415)
pi = 3.1415
> print('звезда равна %c' % 42)
звезда равна *
> print('%d %d %d' % (1, 2, 3))
1 2 3

А вот пара примеров, показывающих, почему одно значение может быть заключено в кортеж:

> a = (1,2,3)
> print('a is %r' % a)
a равно 1
> print('a is %r' % (a,))
a is (1, 2, 3)

В первом случае строковая интерполяция использует первый элемент a в качестве значения вместо того, чтобы использовать все a.

 ~

Глава 6. Выражение и присваивание

значение

Выражение Expression просто оценивает значение. Это может быть полезно, если значение имеет побочный эффект, например, вызов функции, которая устанавливает некоторое глобальное состояние. На верхнем уровне значение выводится, в противном случае оно отбрасывается.

местоположение = значение

Оператор присваивания принимает значение правого операнда и сохраняет его в месте, указанном левым операндом. Левый операнд может быть переменной, местом в списке или местом в словаре.

местоположение op значение

где op - одно из следующих значений:
+=, , -=, =, /=, //=, %=,
\*=, &=, |=, ^=, <<=, >>= 

Оператор присваивания берет значение левого операнда и значение правого операнда и выполняет операцию, обозначенную оператором. Затем результат сохраняется в месте, указанном левым операндом. Здесь есть некоторые тонкости, которые обсуждаются в разделе "Списки и кортежи" главы "Типы данных".

 ~

Глава 7. Поток управления

Snek имеет подмножество операций потока управления Python, включая трейлинг else: блоки для циклов.

 ~

7.1. if

if value : block [ elif value : ... ] [ else: block ]

Оператор If содержит начальный блок if, любое количество блоков elif и затем (необязательно) блок else в следующей структуре:

if if_value :
    утверждения if
elif elif_value :
    elif_высказывания
..
else
    else_statements

Если if_value истинно, то выполняются if_statements. Иначе, если elif_value истинно, то выполняются elif_statements. Если ни одно из значений if или elif не является истинным, то выполняются else_statements.

 ~

7.2. while

while значение : block [ else: block ]

Оператор While состоит из блока while, за которым следует необязательный блок else:

while while_value :
    блок
else:
    блок

While_value оценивается, и если оно оценивается как True, то блок while выполняется. Затем система снова оценивает while_value, и если оно снова становится True, блок while снова выполняется. Так продолжается до тех пор, пока while_value не будет оценено как False.

Когда while_value оценивается как False, выполняется блок else:. Если оператор break выполняется как часть операторов while, то программа сразу же переходит к операторам else*. Если оператор continue выполняется как часть операторов while, то выполнение возвращается к оценке while_value. Часть else:\ (с утверждениями else) является необязательной.

 ~

7.3. for

for name in value : block [ else: block ]

Для каждого значения v в списке значений оператор for присваивает v имя name и затем выполняет блок операторов. Значение может быть задано двумя различными способами: в виде списка, кортежа, словаря или строкового значения, или в виде выражения диапазона, включающего числа:

for name in value:
    for statements
else:
    else statements

В этом случае значение должно быть списком, кортежем, словарем или строкой. Для списков и кортежей значениями являются элементы объекта. Для строк значениями являются строки, составленные из каждого отдельного (ASCII) символа в строке. Для словарей значениями являются ключи в словаре.

for name in range ( start, stop, step ):
    for statements
else:
    else statements

В этой форме оператор for присваивает name диапазон числовых значений. Начиная с start и не выходя за пределы stop, имя получает step, добавляемый на каждой итерации. Start является необязательным; если оно отсутствует, будет использоваться 0. Step также необязателен; если он отсутствует, будет использоваться 1.

> for x in (1,2,3):
+ print(x)
+
1
2
3
> for c in 'hi':
+ print(c)
+
h
i
> a = { 1:2, 3:4 }
> for k in a:
+ print('ключ - %r значение - %r' % (k, a[k]))
+
ключ равен 1 значение равно 2
ключ равен 3 значение равно 4
> for i in range(3):
+ print(i)
+
0
1
2
> for i in range(2, 10, 2):
+ print(i)
+
2
4
6
8

Если оператор break выполняется как часть оператора for, то программа сразу переходит к операторам else. Если оператор continue выполняется как часть оператора for, то программа переходит к присвоению следующего значения имени. В обеих формах часть else: (с утверждениями else) является необязательной.

 ~

7.4. возвращаемое значение

Оператор Return заставляет текущую выполняющуюся функцию немедленно оценить значение в окружающем контексте.

> def r():
+ return 1
+ print('hello')
+
> r()
1

В данном случае оператор print не выполнился, потому что перед ним произошел возврат.

 ~

7.5. break

Оператор Break приводит к завершению ближайшего заключенного оператора while или for. Любое необязательное предложение else:, связанное с оператором while или for, пропускается при выполнении break.

> for x in (1,2):
+ if x == 2:
+ break
+ print(x)
+ else:
+ print('else')
+
1
> for x in (1,2):
+ if x == 3:
+ break
+ print(x)
+ else:
+ print('else')
+
1
2
else

В данном случае первый пример не печатает else из-за правил выполнения оператора break. Второй пример печатает else, потому что оператор break никогда не выполняется.

 ~

7.6. continue

Оператор continue заставляет ближайший заключающий оператор while или for вернуться к той части цикла, которая оценивает условие завершения. В операторах while это место, где оценивается while_value. В операторах for это место, где вычисляется следующее значение в последовательности.

> гласные = 0
> другие = 0
> for a in 'hello, world':
+ if a in 'aeiou':
+ vowels += 1
+ continue
+ other += 1
+
> гласные
3
> другой
9

Оператор continue пропускает выполнение other += 1, иначе other было бы 12.

 ~

7.7. pass

Утверждение pass - это место, которое ничего не делает, и может быть использовано в любом месте, где требуется утверждение, когда выполнение нежелательно.

> if 1 != 2:
+ pass
+ else:
+ print('equal')
+

Этот пример ничего не делает, поскольку условие направляет выполнение через оператор pass.

 ~

Глава 8. Другие утверждения

 ~

8.1. имя импорта

Оператор import игнорируется и является частью Snek, чтобы программы Snek можно было запускать с помощью Python.

> import curses

 ~

8.2. global name [ , name ... ]

Оператор Global помечает имена как нелокальные; присвоение им не приведет к созданию новой переменной.

> g = 0
> def set_local(v):
+ g = v
+
> def set_global(v):
+ global g
+ g = v
+
> set_local(12)
> g
0
> set_global(12)
> g
12
>

Поскольку set_local не включает глобальный оператор g, присвоение g создает новую локальную переменную, которая затем отбрасывается при возврате функции. А вот set_global включает глобальный оператор g, поэтому присваивание g ссылается на глобальную переменную, и изменение будет видно после завершения функции.

 ~

8.3. del location

Оператор Del удаляет либо переменные, либо элементы в списке или словаре.

 ~

8.4. assert value

Если значение равно False, программа выведет AssertionError и остановится. В противном случае программа продолжит выполнение. Это полезно для добавления проверок внутри вашей программы, чтобы помочь обнаружить проблемы раньше.

 ~

Глава 9. Функции

Функции в Snek (как и в любом другом языке) обеспечивают способ инкапсуляции последовательности операций. Они могут быть использованы для документирования действий программы, для сокращения общей длины программы или для скрытия деталей операции от других частей программы.

Функции принимают список "позиционных" параметров, а затем список "именованных" параметров. Все позиционные параметры являются обязательными и передаются вызывающей стороне в том же порядке, в котором они появляются в объявлении. Именованные параметры являются необязательными; они будут установлены в значение по умолчанию, если не будут переданы вызывающей стороной. Они могут появляться в любом порядке в вызове. Каждый из этих параметров присваивается переменной в новой области видимости; переменные в этой новой области видимости будут скрывать глобальные переменные и переменные из других функций с тем же именем. Когда функция возвращается, все переменные в этой новой области видимости отбрасываются.

Дополнительные переменные в этой новой области видимости создаются, когда им присваивается значение, если они не включены в глобальный оператор.

 ~

9.1. def

def fname ( pos1[,posn ...] [, namen=defaultn ...]) : block

Оператор def объявляет(или повторно объявляет) функцию. Все позиционные и именованные параметры видны как локальные переменные во время выполнения функции.

Вот пример функции с двумя параметрами:

> def subtract(a,b):
+ return a - b
+
> subtract(3,2)
1

А вот функция с одним позиционным и двумя именованными параметрами:

> def step(value, times=1, plus=0):
+ return value * times + plus
+
> step(12)
12
> step(12, times=2)
24
> step(12, plus=1)
13
> шаг(12, раз=2, плюс=1)
25

 ~

Глава 10. Стандартные встроенные функции

Snek включает в себя небольшой набор стандартных встроенных функций, но он может быть расширен рядом системно-зависимых функций. В этой главе описывается набор встроенных функций, которые считаются "стандартной" частью языка Snek и предоставляются во всех реализациях Snek.

 ~

10.1. len( value)

Len возвращает количество символов в строке или количество элементов в кортеже, списке или словаре.

> len('hello, world')
12
> len((1,2,3))
3
> len([1,2,3])
3
> len({ 1:2, 3:4, 5:6, 7:8 })
4

10.2. print( value1, value2, ..., end='\n')

Print записывает все свои позиционные параметры на консоль, разделенные пробелами (' '), за которыми следует конечный именованный параметр (по умолчанию: '\\n').

> print('hello world', end='.')
hello world.>
> print('hello', 'world')
привет мир
>

 ~

10.3. sys.stdout.flush()

Смыть вывод на консоль, на случай если где-то есть буферизация.

 ~

10.4. ord( string)

Преобразует первый символ в строке в его ASCII значение.

> ord('A')
65

 ~

10.5. chr( number)

Преобразует значение ASCII в строку из одного символа.

> chr(65)
'A'

 ~

10.6. abs( number)

Вычисляет абсолютное значение числового аргумента. Абсолютное значение числа - это расстояние числа от 0.

> abs(-2)
2

 ~

10.7. math.sqrt( число)

Вычисляет квадратный корень из числового аргумента.

> math.sqrt(2)
1.414214

 ~

Глава 11. Общие системные функции

Эти функции зависят от системы, но обычно доступны. Если они доступны, они будут работать так, как описано здесь.

 ~

11.1. exit( value)

Завершает работу Snek и возвращает операционной системе значение. Как интерпретировать это значение, зависит от операционной системы. В Posix-совместимых системах значение должно быть числом, которое формирует код завершения процесса Snek, причем ноль означает успех, а ненулевое значение - неудачу.

 ~

11.2. time.sleep( seconds)

Сделать паузу на указанное количество времени\(которое может включать дробную часть).

> time.sleep(1)

 ~

11.3. time.monotonic()

Возвращает время (в секундах) с некоторой неопределенной точки отсчета в истории системы. Это время всегда увеличивается, даже если системные часы корректируются(отсюда и название). Поскольку Snek использует для всех чисел значения с плавающей запятой одинарной точности, точка отсчета будет близка к начальному времени системы Snek, поэтому значения могут быть довольно малы.

> time.monotonic()
6.859814

 ~

11.4. random.seed( seed)

Повторно засеивает генератор случайных чисел семенем. Генератор случайных чисел всегда будет генерировать одну и ту же последовательность чисел, если его запустить с одним и тем же seed.

> random.seed(time.monotonic())
>

 ~

11.5. random.randrange( max)

Генерирует случайное целое число от 0 до max-1 включительно.

> random.randrange(10)
3

 ~

Глава 12. Функции ввода

Функции ввода Snek обеспечивают некоторые операции, которые обычно требуются при чтении данных, предоставленных пользователем через последовательный порт.

 ~

12.1. float( value)

Преобразует значение в число. Значение может быть как строкой, так и числом.

> float('10.25')
10.25

 ~

12.2. input( prompt)

Выводит необязательное запрос, а затем ждет, пока пользователь введет текст, завершаемый новой строкой. Возвращается текст без новой строки.

> input('--> ')
--> Hi there
'Hi there'

 ~

12.2.1. int( значение)

Преобразует значение в целое число, округляя в сторону нуля. Значение может быть как строкой, так и числом.

> int('10.75')
10
> int(-10.75)
-10

 ~

12.2.2. str( value)

Преобразует значение (которое может быть любым значением улитки) в строку. Это то же самое, что '%s' % (`значение, )`, но может быть более понятным в некоторых контекстах.

> str(10.75)
'10.75'
> str((1,2,3))
'(1, 2, 3)'
> *str('hello world')
'hello world'

 ~

Глава 13. Математические функции

Математические функции Snek предлагают те же функции, что и математический пакет Python, но с одинарной точностью вместо двойной. Эти функции являются необязательными, но если они предоставлены, то предоставляются все и следуют приведенным здесь определениям.

 ~

13.1. Теоретико-числовые функции и функции представления

math.ceil(x)

Возвращает потолок x, наименьшее целое число, большее или равное x.

math.copysign(x,y)

Возвращает число с величиной (абсолютным значением) x, но со знаком y.

math.fabs(x)

Возвращает абсолютное значение x.

math.factorial(x)

Возвращает факториал x.

math.floor(x)

Возвращает пол x, наибольшее целое число, меньшее или равное x.

math.fmod(x,y)

Возвращает модуль x и y: x - trunc(x/y) * y.

math.frexp(x)

Возвращает нормализованную дробь и экспоненту в кортеже (frac, exp). 0.5 ≤ abs(frac) < 1, и x = frac * pow(2,exp).

math.fsum(l)

Возвращает сумму чисел в l, которое должно быть списком или кортежем.

math.gcd(x,y)

Возвращает наибольший общий делитель x и y.

math.isclose(x,y,rel_val=1e-6,abs_val=0.0)

Возвращает булево значение, указывающее, находятся ли x и y "близко" друг к другу. Это определяется как

abs(x-y) ≤ max(rel_tol * max(abs(a), abs(b)), abs_tol).

math.isfinite(x)

Возвращает True, если x конечен, иначе False.

math.isinf

Возвращает True, если x бесконечен, иначе False.

math.isnan

Возвращает True, если x не является числом, иначе False.

math.ldexp(x,y)

Возвращает x * pow(2,y).

math.modf(x)

Возвращает (x - trunc(x), trunc(x)).

math.remainder(x,y)

Возвращает остаток от x и y: x - round(x/y) * y.

math.trunc

Возвращает усечение x, ближайшее к x целое число, которое не дальше от нуля, чем x.

round(x)

Возвращает ближайшее к x целое число, значения которого находятся посередине между двумя целыми числами, округляющимися от нуля.

 ~

13.2. Силовые и логарифмические функции

math.exp(x)

Возвращает pow(e,x).

math.expm1(x)

Возвращает exp(x)-1.

math.exp2(x)

Возвращает pow(2,x).

math.log(x)

Возвращает натуральный логарифм от x.

math.log1p(x)

Возвращает log(x+1).

math.log2(x)

Возвращает логарифм по основанию 2 от x.

math.log10(x)

Возвращает логарифм по основанию 10 от x.

math.pow(x,y)

Возвращает x, возведенное в степень y.

 ~

13.3. Тригонометрические функции

math.acos(x)

Возвращает косинус дуги x в диапазоне 0 ≤ acos(x) ≤ π.

math.asin(x)

Возвращает синус дуги x в диапазоне -π/2 ≤ asin(x) ≤ π/2.

math.atan(x)

Возвращает тангенс дуги x в диапазоне -π/2 ≤ atan(x) ≤ π/2.

math.atan2(y,x)

Возвращает тангенс дуги y/x в диапазоне -π ≤ atan2(y,x) ≤ π..

math.cos(x)

Возвращает косинус x.

math.hypot(x,y)

Возвращает sqrt(x*x + y*y).

math.sin(x)

Возвращает синус x.

math.tan(x)

Возвращает тангенс угла x.

 ~

13.4. Угловое преобразование

math.degrees(x).

Возвращает x * 180/π.

math.radians(x)

Возвращает x * π/180.

 ~

13.5. Гиперболические функции

math.acosh(x)

Возвращает обратный гиперболический косинус x.

math.asinh(x)

Возвращает обратный гиперболический синус x.

math.atanh(x)

Возвращает обратный гиперболический тангенс x.

math.cosh(x)

Возвращает гиперболический косинус x: (exp(x) + exp(-x)) / 2

math.sinh(x)

Возвращает гиперболический синус x: (exp(x) - exp(-x)) / 2.

math.tanh(x)

Возвращает гиперболический тангенс x: sinh(x) / cosh(x).

 ~

13.6. Специальные функции

math.erf(x)

Возвращает функцию ошибки в точке x.

math.erfc(x)

Возвращает дополнение функции ошибки в точке x. Это 1 - erf(x).

math.gamma(x)

Возвращает гамма-функцию в точке x.

math.lgamma(x)

Возвращает log(gamma(x)).

 ~

13.7. Математические константы

** math.pi**.

Математическая константа π, с доступной точностью.

math.e

Математическая константа e, с доступной точностью.

math.tau

Математическая константа τ, равная 2π, с доступной точностью.

math.inf

Значение с плавающей точкой, которое представляет ∞.

math.nan

Значение с плавающей точкой, представляющее "Не число".

 ~

Глава 14. Функции GPIO

На встроенных устройствах Snek имеет ряд функций, предназначенных для удобного манипулирования пинами GPIO. Snek отслеживает два пина для вывода и один пин для ввода. Два выходных пина называются Power и Direction. Каждая функция вывода определяет, с какими выводами она работает. Все входные и выходные значения находятся в диапазоне от 0 до 1. Цифровые выводы используют только 0 или 1, аналоговые выводы поддерживают весь диапазон значений от 0 до 1.

Входные контакты можно настроить так, чтобы они считывались как 0 или 1, когда ничего не подключено, используя pulldown или pullup. Использование pullnone делает вывод "плавающим" для обеспечения точных аналоговых показаний. Цифровые выводы по умолчанию подтягиваются, аналоговые выводы устанавливаются в режим pullnone.

Выходные контакты либо включены, либо выключены. Значение вывода, который находится в состоянии on, устанавливается в соответствии с текущей мощностью для этого вывода; изменения текущей мощности для вывода вступают в силу немедленно. У вывода off его значение установлено на ноль, но Snek запоминает установленный уровень мощности и восстановит его при включении on.

 ~

14.1. talkto( pin)

Устанавливает текущие выходные пины. Если pin - число, то устанавливаются оба вывода - Power и Direction. Если pin - список или кортеж, то первый элемент устанавливает вывод Power, а второй - вывод Direction.

 ~

14.2. setpower( power)

Устанавливает уровень мощности на текущем выводе Power в power. Если пин Power в данный момент on, то это значение вступает в силу немедленно. В противном случае Snek запоминает желаемый уровень мощности и будет использовать его при включении вывода on. Значения меньше нуля устанавливают мощность на ноль, значения больше единицы устанавливают мощность на единицу.

 ~

14.3. setleft()

Включает текущий вывод направления on.

 ~

14.4. setright()

Включает текущий вывод направления выключает.

 ~

14.5. on()

Включает текущий вывод Power on.

 ~

14.6. off()

Выключает текущий вывод питания выключен.

 ~

14.7. onfor( seconds)

Включает текущий вывод питания вкл, задерживается на секунды и затем выключает текущий вывод питания выкл.

 ~

14.8. read( pin)

Возвращает значение pin. Если это аналоговый вывод, то read возвращает значение от 0 до 1(включительно). Если это цифровой вывод, то read возвращает либо 0, либо 1.

 ~

14.9. pullnone( pin)

Удаляет любые настройки подтягивания или оттягивания для pin, оставляя значение плавающим, когда ничего не подключено. Используйте эту настройку для аналоговых выводов, чтобы получить непрерывные значения, а не просто 0 или 1. Это настройка по умолчанию для аналоговых выводов.

 ~

14.10. pullup( pin)

Назначает подтягивание для pin, так что при чтении будет возвращаться 1, когда ничего не подключено. В этом режиме аналоговые выводы будут возвращать только 0 или 1. Это настройка по умолчанию для цифровых выводов.

 ~

14.11. pulldown( pin)

Назначает подтягивание для pin, так что при чтении будет возвращаться 0, когда ничего не подключено. В этом режиме аналоговые контакты будут возвращать только 0 или 1. Обратите внимание, что некоторые платы не поддерживают этот режим, в этом случае данная функция будет недоступна.

 ~

14.12. stopall()

Выключает все контакты.

 ~

14.13. neopixel( pixels)

Программирует либо набор неопиксельных устройств, подключенных к текущему контакту Power (когда Power и Direction одинаковы), либо набор устройств APA102, подключенных к текущим контактам Power (используется для APA102 Data) и Direction (используется для APA102 Clock) (когда Power и Direction различны). pixels - это либо список/кортеж из трех чисел, либо список/кортеж, каждый элемент которого представляет собой список/кортеж из трех чисел от 0 до 1 для желаемой интенсивности красного, зеленого и синего цветов целевого неопикселя.

> talkto(NEOPIXEL)
> neopixel((0, 0.5, 0))

Этот пример программирует одно устройство NeoPixel, устанавливая его на половинную интенсивность зеленого цвета.

> talkto(NEOPIXEL)
> pixels = [(0.33, 0, 0), (0, 0.66, 0), (0, 0, 1)]
> neopixel(pixels)

Этот пример программирует три устройства NeoPixel, первое из которых настроено на одну треть интенсивности красного, второе - на две трети интенсивности зеленого и последнее - на полную интенсивность синего. Если подключены дополнительные неопиксельные устройства, они не будут изменены. Если подключено меньше устройств, чем указано в предоставленных данных, дополнительные значения будут проигнорированы.

 ~

14.14. tone( frequency)

На устройствах с аудиовыходом устанавливает на выходе этого вывода синусоидальную волну с частотой частота Герц. Амплитуда контролируется настройкой мощности для вывода и тем, включен ли вывод.

> talkto(A0)
> on()
> tone(tone.A)

 ~

14.15. tonefor( частота, секунды)

Устанавливает звуковой сигнал на частоту, включает текущий вывод питания on, делает задержку на секунды и затем выключает текущий вывод питания off.

> talkto(A0)
> tonefor(tone.C, 1)

 ~

14.16. Константы музыкальных нот

Здесь приведены частоты, часто используемые в музыке, начиная со средней C:

Таблица 1. Константы музыкальных нот

Название Нота Частота
tone.C C 261.6255653
tone.Csharp C♯ 277.1826310
tone.Dflat D♭ 277.1826310
tone.D D 293.6647679
tone.Dsharp D♯ 311.1269837
tone.Eflat E♭ 311.1269837
тон.E E 329.6275569
тон.F F 349.2282314
tone.Fsharp F♯ 369.9944227
tone.Gflat G♭ 369.9944227
tone.G G 391.9954360
tone.Gsharp G♯ 415.3046976
тон.Aflat A♭ 415.3046976
tone.A A 440.0000000
тон.Ашарп A♯ 466.1637615
тон.бемоль B♭ 466.1637615
tone.B B 493.8833013

 ~

Глава 15. Встроенные функции EEPROM

Snek на встраиваемых устройствах может включать постоянное хранилище исходного кода. Этот код считывается во время загрузки, что позволяет платам с загруженным Snek работать автономно. Эти функции используются Snekde для получения и размещения программ на устройстве.

 ~

15.1. eeprom.write()

Считывает символы с консоли и записывает их в eeprom до тех пор, пока не будет прочитан символ ^D.

 ~

15.2. eeprom.show()

Выводит текущее содержимое eeprom на консоль. Если в эту функцию передан параметр, то перед текстом будет отправлен символ ^B, а после - ^C. Snekde использует эту функцию для точного захвата текста программы при вызове команды Get.

 ~

15.3. eeprom.load()

Повторно анализирует текущее содержимое eeprom, как это делает Snek во время загрузки.

 ~

15.4. eeprom.erase()

Стереть eeprom.

 ~

15.5. reset()

Перезапустите систему Snek, стерев все содержимое оперативной памяти. В процессе перезапуска Snek перечитает исходный код, хранящийся в eeprom.

 ~

Глава 16. Функция преобразования температуры

Эта функция включена в устройства, имеющие встроенный датчик температуры.

 ~

16.1. temperature( sensorvalue )

Функция преобразования задает параметры, необходимые для преобразования значения датчика температуры в градусы Цельсия.

 ~

Глава 17. Встроенные функции Curses

Curses предоставляет простой механизм для отображения текста на консоли. API разработан таким образом, чтобы быть достаточно совместимым с модулем Python curses, хотя он гораздо менее гибок. Snek поддерживает только ANSI-терминалы и не имеет представления о размерах консоли. Не все реализации Snek предоставляют функции curses.

 ~

17.1. curses.initscr()

Переводит консоль в "визуальный" режим. Отключает эхо. Заставляет stdscr.getch() перестать ждать новой строки.

 ~

17.2. curses.endwin()

Возвращает консоль в "нормальный" режим. Включает эхо. Заставляет stdscr.getch() ждать новых строк.

 ~

17.3. curses.noecho(), curses.echo(),
curses.cbreak(), curses.nocbreak()

Все эти четыре функции не являются операционными и включены в API только для того, чтобы сделать его более совместимым с Python curses.

 ~

17.4. stdscr.nodelay( nodelay )

Если nodelay равно True, то stdscr.getch() вернет -1, если нет ожидающего символа. Если nodelay равно False, то stdscr.getch() заблокирует ожидание возврата символа.

 ~

17.5. stdscr.erase()

Стереть экран.

 ~

17.6. stdscr.addstr( строка, столбец, строка )

Отображает строку в строке, столбце. Строка 0 - это верхняя строка экрана. Столбец 0 - это левый столбец. Курсор оставляется в конце строки.

 ~

17.7. stdscr.move( строка , столбец )

Перемещает курсор в строку, столбец, не отображая там ничего.

 ~

17.8. stdscr.refresh()

Удаляет все ожидающие обновления экрана.

 ~

17.9. stdscr.getch()

Считывает символ с консольного ввода. Возвращает число, обозначающее прочитанный символ, которое может быть преобразовано в строку с помощью chr(c). Если stdscr.nodelay(nodelay) последний раз вызывалась с nodelay = True, то stdscr.getch() немедленно вернет -1, если не ожидается никаких символов.

 ~

Глава 18. Среда разработки Snek

Среда разработки Snek, Snekde, - это программа на языке Python, которая работает под Linux, Mac OS X и Windows для работы с небольшими устройствами под управлением Snek, такими как платы Duemilanove и Metro M0 Express.

 ~

18.1. Запуск Snekde

В Windows и Linux запустите snekde из меню приложений. В Mac OS X Snekde устанавливается вместе с другими файлами Snek в папке Snek в вашей личной папке Applications, которая находится в папке Home. Для запуска дважды щелкните на значке Snekde.

Snekde работает в окне консоли или терминала и не использует мышь, а управляется исключительно с помощью команд клавиатуры.

Snekde разделяет окно на две панели. Верхняя панель - это "панель редактора", в которой находится ваша программа Snek. Нижняя панель - это "консольная панель", в которой происходит обмен данными с устройством Snek.

 ~

18.2. Основная навигация

В верхней части окна вы увидите список команд, которые привязаны к функциональным клавишам. Они нужны для того, чтобы напомнить вам, как управлять Snekde.

Если ваши функциональные клавиши не работают, вы можете использовать клавишу Esc вместе с цифровой клавишей. Нажмите и отпустите клавишу Esc, затем нажмите и отпустите цифровую клавишу. Например, чтобы вызвать команду F1, нажмите и отпустите Esc, затем нажмите и отпустите '1'.

Между двумя панелями находится разделительная линия. В конце этой строки находится имя текущего подключенного устройства Snek, например, /dev/ttyUSB0 в Linux или COM12 в Windows. Если устройство не подключено, появится надпись "<нет устройства>".

Курсор показывает, с какой панелью вы работаете в данный момент. Для переключения между панелями редактора и консоли используйте клавишу F7. Если у вас нет такой клавиши, или она не работает, вы также можете использовать Esc-7 или Ctrl-o (нажмите и удерживайте клавишу Ctrl, нажмите клавишу o, а затем отпустите обе).

Вы можете перемещаться по текущей панели с помощью стрелок, клавиш "домой", "конец" и "страница вверх/страница вниз". Для вырезания/вставки/копирования используются клавиши Ctrl-x, Ctrl-v и Ctrl-c или Esc-x, Esc-v и Esc-c соответственно. Чтобы выделить участок текста для команды Вырезать или Вставить, нажмите Esc-space или Ctrl-space, а затем используйте обычные команды перемещения. Выделенная область текста будет выделена.

 ~

18.3. Подключение к устройству

Чтобы подключиться к устройству, на котором работает Snek, нажмите клавишу F1\ (обычно рядом с клавишей ESC на вашей клавиатуре). В результате в середине экрана появится диалоговое окно со списком всех устройств, на которых может работать Snek (если у вас есть последовательный модем или другое подобное устройство, оно также будет здесь указано). Выберите целевое устройство и нажмите клавишу ENTER.

Не ждите, что в нижней панели что-то произойдет, сначала нужно привлечь внимание устройства.

Переключитесь на панель Console (F7) и нажмите Ctrl-c, чтобы прервать любую запущенную программу Snek. В панели появится приглашение Snek ("> ").

 ~

18.4. Получение и размещение программ на устройстве

!!! *Устройство Snek хранит одну программу в энергонезависимой памяти. Это позволяет настроить устройство таким образом, чтобы оно выполняло некоторые действия при включении без необходимости предварительно связываться с ним.

Команда Get извлекает текущую программу из подключенного устройства и помещает ее в панель редактора.

!!! Команда Put записывает содержимое панели Editor в энергонезависимую память целевого устройства, а затем перезагружает целевое устройство, чтобы оно перезагрузило программу. Обе эти команды прервут любую запущенную программу Snek, прежде чем выполнить какую-либо работу.

 ~

18.5. Загрузка и сохранение программ на хосте

Вы также можете сохранять и загружать программы в файловую систему хоста. Обе эти команды запрашивают имя файла с помощью диалогового окна файла. В верхней части диалога находится имя файла, который необходимо использовать. Остальная часть диалога содержит каталоги и файлы в том же каталоге, что и имя файла. Каталоги заключены в [ ].

При использовании клавиш со стрелками имя файла заменяется на выделенное имя. Вы также можете изменить имя файла, используя клавишу Backspace и вводя новое имя.

Выберите имя файла, нажав клавишу Enter. Если имя является каталогом, то содержимое этого каталога заменит список каталогов и файлов в диалоговом окне. Если имя файла, то он будет использован для загрузки или сохранения.

Чтобы выйти из диалога и пропустить загрузку или сохранение файла, нажмите Escape.

 ~

Приложение A: Снек по Arduino Duemilanove, LilyPad, Nano и Uno

Все эти платы основаны на оригинальном процессоре Arduino ATMega 328. Существует две версии Snek для этих плат: обычная версия и "большая" версия. Обычная версия сосуществует с загрузчиком Optiboot, что делает удобной перепрошивку новыми версиями Snek. Большая версия переписывает загрузчик, обеспечивая дополнительную функциональность.

Snek для этих плат включает функции Common System, EEPROM и GPIO. Большие" версии добавляют функции ввода. Они не включают математические функции, а также функцию pulldown. Snek для этих плат предоставляет предопределенные переменные для всех выводов GPIO:

Snek для LilyPad добавляет встроенные модули 'tone' и 'tonefor', которые посылают звуковой сигнал на вывод D5. Чтобы освободить место для этого, поддержка словарей была удалена.

D0 - D13

Цифровые входные и выходные контакты. По умолчанию, при использовании в качестве входных выводов, Snek применяет подтягивающий резистор к выводу, так что отключенный вывод будет восприниматься как 1. Измените это с помощью функций pullnone или pullup.

A0 - A5

Аналоговый вход и цифровой выход. При использовании в качестве входных выводов Snek возвращает значение 0-1, указывающее отношение напряжения на выводе к 5В. По умолчанию, при использовании в качестве входных выводов, Snek не применяет ни подтягивающий, ни оттягивающий резистор к выводу, поэтому отключенный вывод будет считывать неопределенное значение. Измените это с помощью функций pullnone или pullup.

 ~

A.1. Установка Optiboot на платы ATMega 328

Snek почти заполняет флэш-память ATMega 328P, оставляя место только для небольшого загрузчика optiboot. Этот загрузчик обычно не устанавливается на Duemilanove или Nano, поэтому вам придется установить его вручную с помощью шайбы для программирования, например, устройства USBTiny.

Используйте Arduino IDE для установки загрузчика Optiboot, следуя инструкциям, найденным на веб-сайте Optiboot [https://github.com/Optiboot/optiboot].

 ~

A.2. Установка Snek на платы ATMega 328

Для установки обычной версии, как только ваша плата будет готова к установке snek, вы можете использовать avrdude, чтобы сделать это с помощью Optiboot. В Linux вы можете использовать snek-duemilanove-install (для Duemilanove и Nano), snek-uno-install (для Uno), или snek-lilypad-install (для LilyPad).

$ snek-duemilanove-install

или

$ snek-lilypad-install

или

$ snek-uno-install

На других хостах вам нужно будет запустить 'avrdude' вручную. Для плат Duemilanove или Nano:

$ avrdude -pm328p -carduino -PCOM1 -b115200 -D \
          -U flash:w:snek-duemilanove-1.9.hex:i

Для плат Uno:

$ avrdude -pm328p -carduino -PCOM1 -b115200 -D \
          -U flash:w:snek-uno-1.9.hex:i

Для плат LilyPad:

$ avrdude -pm328p -carduino -PCOM1 -b57600 -D \
          -U flash:w:snek-lilypad-1.9.hex:i

Замените 'COM1' на имя последовательного порта на вашем компьютере.

Чтобы установить "большую" версию, вам нужно использовать устройство программирования, например, usbtiny от Adafruit. После подключения, в Linux вы можете использовать snek-duemilanove-big-install\ (для Duemilanove или Nano), snek-lilypad-big-install\ (для LilyPad), или snek-uno-big-install\ (для Uno):

$ snek-duemilanove-big-install

или

$ snek-lilypad-install-big

или

$ snek-uno-big-install

На других хостах вам нужно будет запустить 'avrdude' вручную:

$ avrdude -V -c usbtiny -p m328p -u -U \
          -U hfuse:w:0xd1:m

$ avrdude -c usbtiny -p m328p \
          -U flash:w:snek-duemilanove-big-1.9.hex:i

или

$ avrdude -V -c usbtiny -p m328p -u -U \
          -U hfuse:w:0xd1:m

$ avrdude -c usbtiny -p m328p \
          -U flash:w:snek-lilypad-big-1.9.hex:i

или

$ avrdude -V -c usbtiny -p m328p -u -U \
          -U hfuse:w:0xd1:m

$ avrdude -c usbtiny -p m328p \
          -U flash:w:snek-uno-big-1.9.hex:i  

 ~

Приложение B: Snek на Arduino Mega

Snek для Mega включает в себя общую систему, EEPROM, вход, GPIO (не включая функцию pullldown) и математические функции. Snek для Mega предоставляет предопределенные переменные для всех пинов GPIO:

D0-D53

Цифровые входные и выходные контакты. По умолчанию, при использовании в качестве входных выводов, Snek применяет подтягивающий резистор к выводу, так что отключенный вывод будет считаться 1. Измените это с помощью функций pullnone или pullup.

A0-A15

Аналоговый вход и цифровой выход. При использовании в качестве входных выводов Snek возвращает значение 0-1, показывающее отношение напряжения на выводе к 5В. По умолчанию, при использовании в качестве входных выводов, Snek не применяет ни подтягивающий, ни оттягивающий резистор к выводу, поэтому отключенный вывод будет считывать неопределенное значение. Измените это с помощью функций pullnone или pullup.

Snek удобно размещается во флэш-памяти ATmega2560, оставляя достаточно места для последовательного загрузчика, поэтому переустановка Snek может быть выполнена через USB. Однако, прошивка по умолчанию, загруженная на ATMega16u2, который работает как преобразователь USB в последовательный порт, не делает никакого управления потоком XON/XOFF, поэтому ее следует заменить перед установкой Snek, так как без нее Snekde не сможет успешно получить или разместить исходный код.

В Linux установка Snek включает сценарий оболочки snek-mega-install для установки бинарного файла с помощью 'avrdude'. Для получения дополнительной информации прочитайте руководство (также включенное в установку) по snek-mega-install.

На других хостах вам нужно будет установить 'avrdude'. Как только вы это сделаете, вы сможете использовать его для установки Snek на устройство. Поскольку бит предохранения EEPROM не может быть установлен таким образом, при выполнении этой операции любая программа Snek, хранящаяся на устройстве, будет стерта. Выясните, к какому порту подключена Mega, используйте это значение для , а затем запустите 'avrdude' следующим образом:

$ avrdude -patmega2560 -cwiring -P<port> -b115200 -D 
          -U flash:w:snek-mega-1.9.hex:i