Содержание

Программа для комплектации электрощитов «1-2-3 schema» в Одессе

Представительство компании Hager в лице компании ООО Электроконтроль предоставляет продукцию торговых марок Hager (Хагер), Berker (Беркер), Tehalit (Техалит), Polo (Поло) в ассортименте: модульные автоматические выключатели, корпусные автоматические выключатели, дифференциальные автоматические выключатели, диф.реле, рубильники, перекидные рубильники, выключатели нагрузки, устройства защитного отключения, реле времени, импульсное реле, суточное реле, сумеречное реле, контакторы, бесшумные контакторы, магнитные пускатели, индикаторы, измерительные приборы, вольтметры, амперметры, разрядники, кнопки, диммеры, датчики движения, проходные клеммы, наборные клеммы, монтажные клеммы, клеммники, вводно-распределительные блоки, фазные шины, кабельные разветвители, промышленные автоматические выключатели, таймеры, минищитки, настенные щитки, напольные щиты, секционные щиты, распределительные щитки, квартирные щитки, щитки электрические, щитки модульные, щиты с монтажной панелью, щиты учетно распределительные, щиты этажные, шкафы монтажные, шкафы распределения электроэнергии, влагозащитные щитки, щитки серий: Volta, Golf, Vector, Orion, Univers, кабельные каналы, перфорированные кабельные каналы, электромонтажные колоны, короба, гибкий офис, напольные кабельные каналы, рулонный канал, универсальные кабельные каналы, кабельные каналы tehalit серий: DA200, BRP, LFR, LFF, BA7A, LFR, DAP, SL, розетки, выключатели, электротехническая продукция серий Polo: Regina, Fiorena, Optima, Hermetica, 5655, Systo, термостаты, розетки для подзарятки USB, розетки VGA, HDMI, S-video, радиосистемы (“Радиошин”), системы KNX, светорегуляторы и многое другое для инженерии в отрасли электромонтажа.

Всё предоставляемое оборудование, компания Электроконтроль поддерживает наличие на складе широкого ассортимента продукции и осуществляет доставку в города на территории Украины, такие как: Автономная республика Крым, Винница, Волынь, Днепропетровск, Донецк, Житомир, Закарпатье, Запорожье, Ивано-Франковск, Киев, Кировоград, Луганск, Львов, Николаев, Одесса, Полтава, Ровно, Суммы, Тернополь, Харьков, Херсон, Хмельницк, Черкассы, Чернигов, Севастополь, Кривой Рог и др. города Украины.

МЦД-3 «Ленинградско-Казанский» — Комплекс градостроительной политики и строительства города Москвы

Перспективный пассажиропоток МЦД-3: 577 тыс. человек в сутки. 

 

 

Длина диаметра 85 км
Время в пути 111 минут
Количество станций

41

13 станций МЦД-3 станут пересадочными на метро и МЦК.

 

 

 

Строительство инфраструктуры

Завершено строительство остановочного пункта Ховрино. 

Ведется реконструкция железнодорожной инфраструктуры возле Казанского вокзала. Развернуты работы по переустройству двухпутного железнодорожного тоннеля 1925 года постройки. Его пути удлинят и развернут в сторону Митьковской соединительной ветви – основного стыковочного звена будущего МЦД-3, объединяющего Ленинградское и Казанское направлении.

Митьковская соединительная ветвь длиной около трех километров между путями Казанского направления с одной стороны и Ленинградского – с другой также будет реконструирована. Для сохранения работы Московской железной дороги с запуском МЦД-3 на ней будет построен дополнительный – четвертый – главный путь.

Таким образом, маршрут третьего диаметра пройдет в обход двух вокзалов: это снизит нагрузку на станцию метро «Комсомольская».

Также рассматривается перспектива строительства нового остановочного пункта Митьково на пересечении Митьковской ветви с улицей Русаковская недалеко от станции метро «Сокольники» Сокольнической и Большой кольцевой линии. Он разместится между существующими станциями Электрозаводская Казанского направления и Рижская – Ленинградского.

 

Проект МЦД-3 реализуется в увязке с высокоскоростной железнодорожной магистралью Москва – Санкт-Петербург. Это позволит оптимизировать сроки и стоимость работ. Интеграция проектов приведет также к созданию первоклассных транспортных хабов, которые свяжут между собой диаметры, метро и высокоскоростную железнодорожную магистраль.

В Москве высокоскоростные поезда будут делать остановки на станциях Крюково (Зеленоград) и Петровско-Разумовская, Рижская, Ленинградский вокзал. Горожане смогут отправляться в Санкт-Петербург, не тратя времени на поездку на Ленинградский вокзал, а пассажиры, прибывающие из Санкт-Петербурга, смогут пересесть на городской транспорт, не доезжая до центра города. 

 

Схема корпусов

Контент страницы

​​  ​​​​​​​​​
  • Главный учебный корпус (корпуса: А, Б, В, Г, Д)
    111250, г.
    Москва, Красноказарменная улица, дом 17
  • Административный корпус (корпуса: Ж, З, И, К, Л)
    111250, г. Москва, Красноказарменная улица, дом 14
  • Корпус Е
    111250, г. Москва, Красноказарменная улица, дом 13, стр. 1
  • Корпус М
    111250, г. Москва, Красноказарменная улица, дом 13
  • Корпус Н
    111250, г. Москва, Красноказарменная улица, дом 13, стр. 6
  • Корпус Р
    111250, г. Москва, Красноказарменная улица, дом 14, стр. 10
  • Корпус C
    111250, г. Москва, Красноказарменная улица, дом 13С
  • Корпус Т
    111250, г. Москва, Красноказарменная улица, дом 17, стр. 4
  • Корпус Ф
    111116, г. Москва, Энергетический проезд, дом 3, стр. 2
  • Корпус X

    111250, г. Москва, Красноказарменная улица, дом 17, стр. 2
  • Дом культуры МЭИ
    111116, г. Москва, Энергетический проезд, дом 3, стр. 1
  • Научно-техническая библиотека МЭИ
    111250, г. Москва, Красноказарменная улица, дом 13
  • Опытный завод
    111116, г. Москва, Красноказарменная улица, дом 17Г, стр. 3
  • Стрелково-спортивный тир МЭИ
    111250, г. Москва, Красноказарменная улица, дом 13, стр. 4
  • Стадион “Энергия”
    111250, г. Москва, 2-й Краснокурсантский проезд, дом 12, стр. 1
  • Спортивно-оздоровительный комплекс МЭИ. Бассейн
    111116, г. Москва, Энергетический проезд, дом 3, стр. 3
  • Санаторий-профилакторий МЭИ
    111116, г. Москва, Энергетическая улица, дом 8, корпус 3
  • Учебно-экспериментальная теплоэлектроцентраль МЭИ
    111250, г. Москва, Красноказарменная улица, дом 17, стр. 5
  • Пункты питания
    Блинная. Корпус Г, 3 этаж
    Буфет. Корпус Б, 2 этаж
    Буфет. Корпус З, 1 этаж
    Буфет. Корпус И, 1 этаж
    Буфет. Корпус К, 1 этаж
    Буфет. Корпус М, 7 этаж
    Буфет. Корпус С, цокольный этаж.
    Кафе. Корпус М, 1 этаж
    Столовая №1. Корпус В, 0 этаж
    Столовая №5. Корпус М, 5 этаж
    Столовая №10 ул. Лапина, д. 17б
    Пиццерия. Корпус В, 0 этаж
  • Общежития
    111116, г. Москва, Энергетическая улица, дом 6
    111116, г. Москва, Энергетическая улица, дом 10, корпус 1
    111116, г. Москва, Энергетическая улица, дом 14, корпус 1
    111116, г. Москва, Энергетическая улица, дом 14, корпус 4
    111116, г. Москва, Энергетическая улица, дом 18, корпус 2
    111116, г. Москва, Энергетическая улица, дом 18, корпус 1
    111020, г. Москва, 1-я Синичкина улица, дом 3, корпус 1
    111020, г. Москва, 1-я Синичкина улица, дом 3, корпус 1А
​​​​​​​​​​​ ​​

Схема лечения ОРВИ с подозрением или подтвержденным COVID-19

Если вы болеете 1-3-ий день, сразу начинайте прием ВСЕХ ниже перечисленных препаратов по четырем пунктам:

  1. Один из противовирусных препаратов: ингавирин 90мг 1 т утром 7 дней или арбидол 200 мг*4 р в день, или кагоцел по схеме; после уточнения диагноза COVID-19 возможен прием фавипиравира (коронавир) по схеме. Возможно сочетание с гриппферон по 3 кап 5 раза в день 10-15 дней.
    Беременным и кормящим женщинам – только гриппферон по 3 кап 5 раза в день 10-15 дней и виферон в свечах по 3 000 000 МЕ 2 раза в сутки 10 дней.
  2. Жаропонижающие препараты: парацетамол 0,5 по 1 табл. до 4 раз в день при лихорадке свыше 38 гр., можно сочетать с ибупрофеном 400мг * 3раза в день или с аспирином 0,5*3раза в день. Для усиления эффекта можно сочетать с приемом спазмолитиков: папаверин, но-шпа, баралгин, спазмалгон…
  3. Бромгексин 8 мг 4р в день или амброксол по 1 т 4р (отхаркивающий препарат, также блокирует попадание вируса в клетку), 2 недели. При кашле можно добавить таблетки от кашля (термопсис с содой) по 5 табл. на 0,5 стакана горячей воды – выпить в горячем виде мелкими глотками.
  4. Верошпирон 50 мг утром – 2-3 недели (считается слабым мочегонным препаратом, но в данном случае используется для снижения тестостерона, блокады рецепторов АРА 2, на которые садится вирус, уменьшения фиброза легочной ткани, чтобы не было осложнений после перенесенной инфекции, одышки)
    Длительность лечения, если нет ухудшения состояния, составляет 2 недели, потом можно отменить бромгексин, верошпирон и препараты, разжижающие кровь.

Если у вас на 4 день болезни сохраняется или нарастает температура, появляется одышка, кашель … необходимо ДОБАВИТЬ к лечению следующие препараты:

  1. Противовоспалительные гормональные препараты являются препаратами первого выбора:
    дексаметазон 0,5 мг по 2 табл. 2 раза в день (утром и днем), после еды, 5-7 дней , затем доза должна ПОСТЕПЕННО уменьшаться — на 0,5 (половину) таблетки 1 раз в 3-5 дней (чем медленней, тем лучше) до полной отмены. На шестой день приема дексаметазона нужно уточнить дальнейшую схему снижения дозы препарата у лечащего врача.
    Дексаметазон можно заменить следующими препаратами: метипред (метилпреднизолон) 4 мг, преднизолон 5 мг — принимать по той же схеме.
  2. Применение гормональной терапии должно быть в сочетании с антикоагулянтной терапией (разжижение крови) для профилактики тромбообразования.
    эликвис 2,5 мг по 2 табл.*2 раза в день (или ксарелто 10 мг (15 мг, 20 мг) утром) – в течение 5-7 дней, затем можно снизить дозу эликвиса до 2,5 мг 2 раза в день и принимать еще до 3 недель.
    При невозможности приобретения или приема этих препаратов, можно начать прием курантила или дипиридамола по 75 мг * 2раза в день (улучшает микроциркуляцию, для профилактики тромбов) + аспирин 500 мг по ¼ таблетке после ужина. Или клопидогрел 75 мг утром.
  3. Т.к. противовоспалительные препараты раздражают слизистую оболочку желудка, необходимо начать прием следующих препаратов:
    фамотидин 40 мг на ночь или нольпаза 0,02 или омепразол 0,02 по 1 т*2раза в день на весь срок, пока принимаем гормоны.
  4. При тошноте можно принимать церукал по 1 т 3 раза за 30 мин до еды или мотилиум супензия по 1 ч.л. (5 мл.) при тошноте; при нарушении стула – лоперамид по 1 капсуле 1-2 раза в день.
  5. Необходимо выпивать до 1,5 литров в сутки жидкости (минеральная вода) – можно выпивать постепенно, по 0,5 стакана в час.
  6. Присоединяем антибактериальную терапию НЕ РАНЕЕ 7-ГО ДНЯ ПОВЫШЕННОЙ ТЕМПЕРАТУРЫ:
    азитромицин (сумамед) 500 мг 1 раз в день 3 дня или амоксиклав (флемоклав, флемоксин) 500 мг по 1 табл. 3раза в день на 7- 10 дней или левофлоксацин 500 мг по 1 табл. 2 раза в день 7 дней или другой антибиотик.

Дополнительно с первых дней заболевания в течении 14 дней, а при необходимости и дольше, можно принимать:

  • витамин Д ( аквадетрим или вигантол) по 8-10 капель в день ( помогают организму бороться с вирусом, при вирусной инфекции возникает очень сильный дефицит витамина Д) – на 1 месяц
  • препараты цинка 15-50 мг в день (помогают организму бороться с вирусом)
  • витамин С по 500 мг в сутки до 1 месяца.

Схема системы тахографа и тахометра МАЗ-6430, двигатели ЯМЗ, MAN, Евро-1, 2, 3, БКА-3, 643008-3700001 И.

Схема системы тахографа и тахометра МАЗ-6430, двигатели ЯМЗ, MAN, Евро-1, 2, 3, БКА-3, 643008-3700001 И.
  • Перечень элементов в схемах МАЗ-6430, двигатели ЯМЗ, MAN, Евро-1, 2, 3, БКА-3, 643008-3700001 И.
  • Нумерация контактов колодок электрооборудования МАЗ-6430, двигатели ЯМЗ, MAN, Евро-1, 2, 3, БКА-3, 643008-3700001 И.
  • Схемы МАЗ-6430, двигатели ЯМЗ, MAN, Евро-1, 2, 3, БКА-3, 643008-3700001 И.
  • Схема МАЗ.

Схема системы тахографа и тахометра МАЗ-6430, двигатели ЯМЗ, MAN, Евро-1, 2, 3, БКА-3, 643008-3700001 И.

Система тахографа и тахометра для автомобилей с двигателями MAN.

Система тахографа и тахометра для автомобилей с двигателями ЯМЗ.

Поделиться ссылкой:

Похожие статьи

  • Схема подключения электрофакельного устройства (ЭФУ) МАЗ-6430, двигатели ЯМЗ, MAN, Евро-1, 2, 3, БКА-3, 643008-3700001 И.
  • Расположение элементов в блоке контроля аппаратуры МАЗ-6430, двигатели ЯМЗ, MAN, Евро-1, 2, 3, БКА-3, 643008-3700001 И.
  • Схема подключения блокировки демультипликатора и датчиков засорённости фильтров МАЗ-6430, двигатели ЯМЗ, MAN, Евро-1, 2, 3, БКА-3, 643008-3700001 И.
  • Схема системы глушения двигателя МАЗ-6430, двигатели ЯМЗ, MAN, Евро-1, 2, 3, БКА-3, 643008-3700001 И.
  • Схема подключения звуковых сигналов МАЗ-6430, двигатели ЯМЗ, MAN, Евро-1, 2, 3, БКА-3, 643008-3700001 И.
  • Схема подключения блокировки межколёсных и межосевого дифференциалов МАЗ-6430, двигатели ЯМЗ, MAN, Евро-1, 2, 3, БКА-3, 643008-3700001 И.
  • Схема подключения указателей и аварийных ламп МАЗ-6430, двигатели ЯМЗ, MAN, Евро-1, 2, 3, БКА-3, 643008-3700001 И.
  • Схема системы сигнализации сигнала торможения, ручного тормоза и заднего хода МАЗ-6430, двигатели ЯМЗ, MAN, Евро-1, 2, 3, БКА-3, 643008-3700001 И.
  • Схема системы управления габаритными огнями МАЗ-6430, двигатели ЯМЗ, MAN, Евро-1, 2, 3, БКА-3, 643008-3700001 И.
  • Схема системы управления ближним, дальним и дополнительным дальним светом фар МАЗ-6430, двигатели ЯМЗ, MAN, Евро-1, 2, 3, БКА-3, 643008-3700001 И.
  • Схема системы сигнализации поворотов и аварийной МАЗ-6430, двигатели ЯМЗ, MAN, Евро-1, 2, 3, БКА-3, 643008-3700001 И.
  • Схема системы электропитания МАЗ-6430, двигатели ЯМЗ, MAN, Евро-1, 2, 3, БКА-3, 643008-3700001 И.
  • Нумерация контактов колодок электрооборудования МАЗ-6430, двигатели ЯМЗ, MAN, Евро-1, 2, 3, БКА-3, 643008-3700001 И.
  • Схема электрооборудования нагревателей МАЗ-6430, двигатели ЯМЗ, MAN, Евро-1, 2, 3, БКА-3, 643008-3700001 И.
  • Схема системы управления стеклоочистителем и стеклоомывателем МАЗ-6430, двигатели ЯМЗ, MAN, Евро-1, 2, 3, БКА-3, 643008-3700001 И.

CITEL 821730234 DAC1-13VG-31-275 УЗИП Тип 1+2+3, Схема (3+1), 4 полюса, TT-TNS, UN230/UC275 Vac, Iimp=12,5kA, Itota=50kA, In=20kA, Imax=50kA (сигнализация визуальная)

Банковский перевод: счет на оплату формируется после оформления заказа или отправки заявки в произвольной форме на электронную почту [email protected] ru. Специалист свяжется с вами для уточнения деталей.

Самовывоз с нашего склада:
По адресу: Московская область, Люберецкий район, п. Томилино, мкр. Птицефабрика, стр. лит. А, офис 109. Мы есть на Яндекс.Карты.

Доставка до двери
Осуществляется курьерской службой или транспортной компанией (на Ваш выбор).
Мы работаем с ведущими транспортными компаниями и доставляем заказы во все регионы России и Казахстана.

Доставка до терминала
Транспортной компании в Москва – БЕСПЛАТНО.

тактика, расстановка, плюсы и минусы

Автор Роман Новиков На чтение 6 мин Просмотров 25. 1к. Опубликовано

Друзья, всем привет! Мы продолжаем знакомить вас с самыми популярными тактиками в футболе. На очереди схема 3-5-2, которая в последнее время набирает популярность в мировом и российском футболе. В этой статье мы разберем особенности расстановки 3-5-2, ее основные плюсы и минусы. Поехали!

Кликабельное оглавление для удобства поиска информации 👇

Особенности схемы 3-5-2

Расстановка 3-5-2 включает в себя:

  • Трех защитников
  • Трех полузащитников
  • Двух латералей
  • Двух нападающих
Тактическая схема 3-5-2

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

Когда команда остается без мяча, схема 3-5-2 трансформируется в 5-3-2, поэтому будет неправильно рассматривать данные схемы отдельно.

Сначала может показаться, что расстановка 3-5-2 больше нацелена на атаку. Всего 3 защитника, целых 5 полузащитников и 2 нападающих. Но это не так. При обороне игроки фланга опускаются ниже, образуя линию в 5 защитников. В центре поля также образуется плотный блок из трех полузащитников.

Пара нападающих всегда готова выбежать в контратаку. Наиболее эффективной связкой является пара: габаритный форвард таранного типа + резкий скоростной нападающий. Пример: Ромелу Лукаку и Лаутаро Мартинес в миланском «Интере».

Ромелу Лукаку и Лаутаро Мартинес в составе миланского «Интера»

В прошлых статьях мы разбирали другие тактические схемы. Прикрепляю ссылки. Обязательно ознакомьтесь!

  1. Схема 4-3-3 в футболе: позиции игроков, тактика, плюсы и минусы

  2. Схема 4-4-2 в футболе: как работает, вариации, плюсы и минусы

  3. Расстановка 4-2-3-1 в футболе: тактика, позиции, плюсы и минусы

Игра в атаке при схеме 3-5-2

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

Посмотрите на рисунок 1.

Рис.1. Схема 3-5-2 в атаке

Что мы имеем:

  • Два нападающих прикрепляются к защитникам, сковывая их
  • Крайние защитники соперника играют по латералям
  • Два центральных полузащитника «красных» (№10 и №8) находятся под опекой
  • Крайние полузащитники «синих» (№9 и №10) играют по крайним центральным защитникам

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

Конечно, команда «синих» может поставить игрока, который будет играть персонально по опорнику. Тогда расположение игроков на поле будет следующим (рис. 2):

Рис. 2. Расстановка 3-5-2 — игра в атаке

Какая ситуация здесь:

  • По опорнику «красных» играет игрок, поэтому выходить в атаку через него будет затруднительно
  • Игроки «синих» (№9 и №10) вынуждены играть персонально по центральным полузащитникам, хотя в прошлой ситуации они играли по крайним ЦЗ

Таким образом, крайние ЦЗ «красных» могут спокойно входить в свободные коридоры, создавая преимущество 3 в 2 во флангах и полуфлангах.

Более подробный разбор игровых моментов вы можете посмотреть в следующем видео:

Рекомендуем к прочтению: Обзор самых популярных тактических схем в футболе


 

Игра в обороне при схеме 3-5-2

Игра в 5 защитников при обороне позволяет:

  1. Создавать численное преимущество на отдельных участках поля

Наличие лишнего игрока в обороне позволяет создавать численное превосходство над атакующей командой. Например, при атаке с фланга крайний центральный защитник может смело идти на подстраховку к латералю. Кроме него есть еще два защитника в штрафной, которые могут присмотреть за нападающими (рис. 3).

При игре в 4 защитника центрдеф не всегда может обеспечить такую поддержку крайним защитникам.

Рис.3. Игра в обороне при схеме 5-3-2
  1. Покрывать всю ширину поля (нейтрализация угрозы с флангов)

Слабым местом расстановок с четырьмя защитниками являются фланги. При быстром перемещении мяча с фланга на фланг оборона не всегда успевает перестроиться и занять правильные позиции. Эту проблему может решить использование расстановки 5-3-2.

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

Плюсы и минусы расстановки 3-5-2

Надежная оборона

Хороший контроль мяча

Вариативность схемы (может трансформироваться в 5-3-2, 3-4-3, 3-3-4, 5-4-1)

Тяжело найти хороших исполнителей на позиции латералей

Образование свободных зон на флангах при потере мяча

Какие клубы играют по схеме 3-5-2?

Миланский «Интер» под руководством Антонио Конте успешно использует схему 3-5-2. Миланцы по итогам чемпионата Италии 2019/20 лишь на одно очко отстали от «Ювентуса» в борьбе за скудетто.

В качестве латералей Конте чаще всего использует Эшли Янга, Антонио Кандреву, Данило Д’Амброзио и Виктора Мозеса. Ромелу Лукаку и Лаутаро Мартенес исполняют пару нападающих.

Миланский «Интер» образца 2020 года — расстановка 3-5-2

Если говорить о российских футбольных клубах, то можно вспомнить московский ЦСКА, который стал обладателем Кубка УЕФА в 2005 году, играя по схеме с тремя защитниками.

Кроме того, Курбан Бердыев в «Рубине» и «Роcтове» практиковал схему 3-5-2 и побеждал такие команды, как «Барселона» и «Бавария».

Команды, играющие в 5 защитников сзади, часто называют автобусами. В одной из наших статей мы рассказывали о том, как взломать автобус в футболе. Рекомендуем к прочтению!

Заключение

В этой статье мы рассказали, как работает схема 3-5-2 в футболе. Если статья оказалась для вас полезной, поделитесь ею со своими друзьями.

Добавляйте сайт в закладки и ждите новых публикаций.

До новых встреч!

CSE 341 — Основы схемы

CSE 341 — Основы схемы

Схема профиля

  • диалект Лиспа
  • в основном функциональные (но не чисто функциональные)
  • динамическая типизация; безопасный тип
  • исключительно хранилище на основе кучи с GC
  • передача по значению с семантикой указателя
  • с лексической областью видимости (изначально Lisp использовал динамическую область видимости)
  • первоклассные функции
  • анонимные функции
  • синтаксически простой, правильный (но много скобок)
    • все по спискам!
    • эквивалентность данных программы (это делает легко писать программы Scheme, которые обрабатывают/производят другие программы, т. грамм. компиляторы, редакторы структур, отладчики и т.д.)
  • обычно может быть запущен как интерпретированный, так и скомпилированный

Области применения Лиспа:

  • ИИ (экспертные системы, планирование и т. д.)
  • Моделирование, Моделирование
  • Программирование приложений (emacs, CAD, Mathematica)
  • Быстрое прототипирование
Лисп был разработан в конце 50-х Джоном Маккарти. Диалект Схемы был разработан Гаем Стилом и Джерри Суссманом в середине 70-х.В 80-е годы Был разработан стандарт Common Lisp. Common Lisp — это язык кухонной раковины: много много особенностей.

Типы данных и операции примитивной схемы

Некоторые примитивные ( atomic ) типы данных:
  • номеров
    • целых чисел (примеры: 1, 4, -3, 0)
    • реалов (примеры: 0,0, 3,5, 1,23E+10)
    • рациональные числа (например, 2/3, 5/2)
  • символов (например, fred, x, a12, набор!)
  • логическое значение: Схема использует специальные символы #f и #t для представления ложного и истинный.
  • строк (например, «привет, матрос»)
  • символов (например, #\c)
Регистр обычно не имеет значения (за исключением символов или строк). Примечание что у вас могут быть забавные символы, такие как + или – или ! во время символы. (Однако у вас не может быть скобок.) Вот некоторые из основных операторы, предусмотренные этой схемой для указанных выше типов данных.
  • Арифметические операторы (+, -, *, /, абс, кврт)
  • Относительный (=, <, >, <=, >=) (для чисел)
  • Относительный (eqv?, равный?) для произвольных данных (подробнее об этом позже)
  • Логические (и, или, нет): и и или являются логическими операторами короткого замыкания.
Некоторые операторы являются предикатами , то есть являются тестами на истинность. В Scheme они возвращают #f или #t. Особенность: в MIT Scheme пустой список эквивалентен #f, а #f печатается как (). Но хорошо стиль заключается в том, чтобы писать #t или #f всякий раз, когда вы имеете в виду истину или ложь, и write(), когда вы действительно имеете в виду пустой список. См. также “Булево Особенности» ниже.
  • номер? целое число? пара? символ? логический? нить?
  • экв? равный?
  • = < > <= >=

Применение операторов, функций

Итак, мы знаем имена нескольких операторов.Как мы их используем? Схема предоставляет нам единый синтаксис для вызова функций:
  (функция arg1 arg2 ... argN)
 

Это означает, что все операторы, включая арифметические, имеют Синтаксис префикса . Аргументы передаются по значению (кроме специальные формы , обсуждаемые позже, позволяющие использовать такие приятные вещи, как короткое замыкание).

Примеры:
  (+ 2 3)
  (абс -4)
  (+ (* 2 3) 8)
  (+ 3 4 5 1)
  ;; обратите внимание, что + и * могут принимать произвольное количество аргументов
  ;; на самом деле так может - и/но у вас голова закружится, пытаясь вспомнить
  ;; что это значит
  ;;
  ;; точка с запятой означает, что остальная часть строки является комментарием
 

Тип данных списка

Возможно, самым важным встроенным типом данных в Scheme является список. В Scheme списки не ограничены, возможно, неоднородны. коллекции данных. Примеры:
  (Икс)
  (Элмер Фадд)
  (2 3 5 7 11)
  (2 3 х у "зоопарк" 2.9)
  ()
 
Представление списков в виде прямоугольников и стрелок:
                 _______________ ________________
                | | | | | |
                | о | ----|----->| о | о |
                |___|___|_______| |____|___|___|___|
                    | | |
                    | | |
                   Элмер Фадд (англ.)
 
Или
                 _______________ _____________
                | | | | | / |
                | о | ----|----->| о | / |
                |___|___|_______| |____|___|/___|
                    | |
                    | |
                   Элмер Фадд
 

Примечания:

  • (х) не то же самое, что х
  • () — пустой список
  • Списки списков: ((a b) (c d)) или ((fred) ((x)))
  • Списки схем могут содержать элементы разных типов: (1 1.5 х (а) ((7)))
Вот несколько важных функций, которые работают со списками:
  • length — длина списка
  • равно? — проверить, равны ли два списка (рекурсивно)
  • автомобиль — первый элемент списка
  • cdr — остаток списка
  • минусы – создать новую ячейку списка (также известную как ячейка cons )
  • список — составить список

(Для вашего удобства Схема также предопределяет составы вагон и cdr , эл. г., (кадр с) г. определить d как (car (cdr s)) .)

Предикаты для списков:
  • ноль? — список пуст?
  • пара? — это непустой список?

Вычисление выражений

Пользователи обычно взаимодействуют со схемой через read-eval-print. цикл ( REPL ). Схема ожидает, пока пользователь введет выражение, читает его, оценивает и печатает возвращаемое значение. Выражения схемы (часто называемые S-выражениями , для Символические выражения ) являются либо списками, либо атомами.Списки состоит из других S-выражений (обратите внимание на рекурсивное определение). Списки часто используются для представления вызовов функций, где список состоит из имени функции, за которым следуют ее аргументы. Однако списки также может использоваться для представления произвольных коллекций данных. В этих заметках мы обычно пишем:
 => <возвращаемое значение>
 
когда мы хотим показать S-выражение и оценку этого S-выражение. Например:
  (+ 2 3) => 5
  (против 1 () ) => (1)
 
Правила оценки:
  1. Числа, строки, #f и #t являются литералами, т.е. оценить для себя.
  2. Символы рассматриваются как переменные, и для их оценки их привязки просматриваются в текущей среде.
  3. Для списков первый элемент определяет функцию. Оставшиеся элементы списка определяют аргументы. Оцените первый элемент в текущих условиях для найти функцию и оценить каждую из аргументы в текущей среде и вызовите функцию для этих значений. Например:
      (+ 2 3) => 5
      (+ (* 3 3) 10) => 19
      (= 10 (+ 4 6)) => #t
     

Использование символов (атомов) и списков в качестве данных

Если мы попытаемся оценить (перечислите Элмера Фадда) мы получим ошибку.Почему? Потому что Схема будет рассматривать атом elmer как имя переменной и пытаться искать за его привязку, которую он не найдет. Поэтому нам нужно «цитировать» имена Элмер и Фадд, что означает, что мы хочу схему относиться к ним буквально. Схема предоставляет синтаксис для этого. Оценка объектов в кавычках заключается в том, что объект в кавычках оценивает сам себя.
'х => х
(список Элмера Фадда) => ошибка! Элмер несвязанный символ
(список 'элмер 'фадд) => (элмер фадд)
(Элмер Фадд) => ошибка! Элмер - неизвестная функция
'(Элмер Фадд) => (Элмер Фадд)
(равно? (x) (x)) => ошибка! х неизвестная функция
(равно? '(x) '(x)) => #t
(cons 'x'(y z)) => (x y z)
(против 'х () ) => (х)
(автомобиль '(1 2 3)) => 1
(cdr (cons 1 '(2 3))) => (2 3)
 
Обратите внимание, что есть 3 способа составить список:
  1. ‘(xyz) => (xyz)
  2. (против ‘x (против ‘y (против ‘z () ))) => (x y z)
  3. (список ‘x ‘y ‘z) => (x y z)
Внутри заключенные в кавычки символы и списки представляются с помощью специального функциональная цитата.Когда читатель читает «(a b) это переводит это в (цитата (a b)), который затем передается на оценщик. Когда оценщик видит выражение вида (цитата s-expr) он просто возвращает s-expr. цитата иногда называется «особой формой», потому что, в отличие от большинства других операций Схемы, она не оценивает свой аргумент. Кавычка является примером того, что называется «синтаксическим сахаром».
  'х => х
  (кавычки х) => х
 
(Алан Перлис: «Синтаксический сахар вызывает рак точки с запятой».)

Переменные

Схема имеет как локальные, так и глобальные переменные. В схеме переменная имя, которое привязано к некоторому объекту данных (с помощью указателя). Там нет объявлений типов для переменных. Правило оценки символы: символ оценивается как значение переменной, которую он называет. Мы можно связывать переменные с помощью специальной формы определить:
(определить выражение символа)
 

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

Строка ниже объявляет переменную с именем clam (если она не существует) и делает его ссылкой на 17:

 (определение моллюска 17)

моллюск => 17

(определение моллюска 23) ; это привязывает моллюска к 23

(+ моллюск 1) => 24
 
(определить bert '(a b c))
(определить Эрни Берта)
 
Схема использует указатели: теперь bert и ernie указывают на один и тот же список.

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

Переменные с лексической областью действия с let и let*

Мы используем специальную форму let для объявления и привязки локальных, временные переменные. Пример:
;; общая форма let
(пусть ((имя1 значение1)
      (имя2 значение2)
...
      (имяN значениеN))
   выражение1
   выражение2
   ...
   выражениеQ)

;; перевернуть список и удвоить его

;; менее эффективная версия:
(определить (r2 x)
  (добавить (обратный х) (обратный х)))

;; более эффективная версия:
(определить (r2 x)
  (пусть ((r (обратный x)))
        (дописать р р)))
 
Единственная проблема с Let заключается в том, что пока создаются привязки, выражения не могут ссылаться на привязки, которые были сделаны ранее. Например, это не работает, так как x неизвестен вне тела:
(пусть ((х 3)
      (у (+ х 1)))
    (+ х у))
 
Чтобы обойти эту проблему, Scheme предоставляет нам let*:
(пусть* ((х 3)
      (у (+ х 1)))
    (+ х у))
 

Определение собственных функций

Lambdas: анонимные функции

Вы можете использовать специальную форму lambda для создания анонимные функции. Эта специальная форма занимает

(лямбда (парам1 параметр2 ... параметр) ; список формальностей
        выражение) ; тело
 

лямбда-выражение оценивается как анонимная функция который при применении (выполнении) принимает k аргументов и возвращает результат оценки expr . Как и следовало ожидать, параметры имеют лексическую область видимости и могут использоваться только в выражение .

Пример:

(лямбда (x1 x2)
        (* (- х1 х2) (- х1 х2)))
 

Оценка приведенного выше примера приводит только к анонимной функции, но мы пока ничего с ним не делаем. Результат Выражение lambda можно применить напрямую, предоставив аргументы, как в этом примере, который оценивается как 49:

((лямбда (x1 x2)
         (* (- х1 х2) (- х1 х2)))
 2-5) ;

  

Определение именованных функций

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

(определить квадратную разность
        (лямбда (x1 x2)
                (* (- х1 х2) (- х1 х2))))
 

Поскольку определение функций является очень распространенной задачей, Scheme предоставляет специальная сокращенная версия определяет , которая не использует лямбда явно:

(определить (имя функции param1 param2 . ..парамк)
        выражение)
 

Вот еще несколько примеров использования определения в этом путь:

(определить (двойной х)
        (* 2 х))

(двойное 4) => 8


(определить (от Цельсия до Фаренгейта c)
        (+ (* 1,8 с) 32,0))

(100,0 градусов Цельсия в градусы Фаренгейта) => 212,0
 
x в функции double является формальным параметр. Он имеет область видимости только внутри функции. Рассмотрим три разные x вот тут...
(определить х 10)

(определить (добавить1 х)
  (+ х 1))

(определить (двойное добавление x)
  (двойной (добавить1 х)))

(двойное добавление x) => 22
 

Функции могут принимать 0 аргументов:

(определить (проверить) 3)
(тест) => 3
 

Обратите внимание, что это не то же самое, что привязка переменной к значение:

(определить не функцию 3)
не-функция => 3
(not-a-function) => ;Объект 3 неприменим.

Равенство и идентичность: равно?, экв?, экв?

Scheme предоставляет три примитива для проверки равенства и идентичности:
  1. экв? это сравнение указателей. Он возвращает #t тогда и только тогда, когда его аргументы буквально относятся к одним и тем же объектам в памяти. Символы уникальны ('fred всегда вычисляет один и тот же объект). Два одинаковых символа равны. Две переменные которые относятся к одному и тому же объекту, равны.
  2. экв? это как экв? но делает правильные вещи при сравнении числа.экв? возвращает #t тогда и только тогда, когда аргументы eq или , если его аргументы являются числами, которые имеют такое же значение. экв? не преобразовывать целые числа в числа с плавающей запятой при сравнении целых чисел и чисел с плавающей запятой.
  3. равно? возвращает true, если его аргументы имеют одинаковую структуру. Формально мы можем определить равный? рекурсивно. равный? возвращает #t, если его аргументы равны eqv, или если его аргументы - это списки, соответствующие элементы которых равны (обратите внимание на рекурсию). Два объекта, которые являются eq, являются одновременно eqv и равный.Два объекта равны, но не обязательно экв. Два объекта, которые равны не обязательно eqv или экв. эквалайзер иногда называется личностью сравнение и равенство называется сравнением на равенство.
Примеры:
(определить моллюск '(1 2 3))
(определение моллюска осьминога) ; моллюск и осьминог относятся к одному и тому же списку

(eq? 'моллюск 'моллюск) => #t
(eq? моллюск моллюск) => #t
(eq? моллюск осьминог) => #t
(eq? моллюск '(1 2 3)) => #f ; (или (), в схеме Массачусетского технологического института)
(экв? '(1 2 3) '(1 2 3)) => #f
(экв? 10 10) => #t ; (обычно, но зависит от реализации)
(уравнение 10.0 10.0) => #f ; (обычно, но зависит от реализации)
(экв? 10 10) => #t ; всегда
(экв? 10.0 10.0) => #t ; всегда
(экв? 10.0 10) => #f ; нет преобразования между типами
(равно? моллюск '(1 2 3)) => #t
(равно? '(1 2 3) '(1 2 3)) => #t
 
Схема дает = для сравнения два числа и приведут один тип к другому. Например, (равно? 0 0.0) возвращает #f , но (= 0 0.0) возвращает #t .

Логические операторы

Схема предоставляет нам несколько полезных логических операторов, в том числе и, или, и нет. Операторы и и/или специальные формы и не обязательно оценить все аргументы. Они просто оценивают столько аргументов, сколько необходимо решить, следует ли вернуть #t или #f (например, && и || операторы в С++). Однако можно было легко написать версию, которая оценивает все его аргументы.
(и expr1 expr2 ... expr-n)
; вернуть true, если все выражения верны
; ... или, точнее, вернуть expr-n, если все expr оцениваются как
; что-то кроме #f. В противном случае вернуть #f

(и (равно? 2 3) (равно? 2 2) #t) => #f

(или expr1 expr2 ... expr-n)
; вернуть true, если хотя бы одно из expr истинно
; ... или, точнее, вернуть выражение-j, если выражение-j является первым выражением, которое
; оценивается чем-то другим, кроме #f. В противном случае вернуть #f.

(или (равно? 2 3) (равно? 2 2) #t) => #t

(или (равно? 2 3) 'fred (равно? 3 (/ 1 0))) => 'fred

(определить (однозначное число x)
   (и (> x 0) ( #t
 

Булевы особенности

В схеме R4 пустой список эквивалентен #f, а все остальное эквивалентно #t. Однако в R5 пустое список также эквивалентен #t! Мораль: используйте только #f и #t для логических значений. константы.

Условные обозначения

, если специальная форма

(если условие true_expression false_expression)

Если условие оценивается как истинное, то результат оценка возвращает true_expression ; иначе возвращается результат оценки false_expression . if это специальная форма, например кавычка , потому что она , а не , автоматически оценивает все свои аргументы.

(если (= 5 (+ 2 3)) 10 20) => 10
(если (= 0 1) (/ 1 0) (+ 2 3)) => 5
; обратите внимание, что (/ 1 0) не оценивается

(определить (мой-макс х у)
   (если (> х у) х у))

(мой-макс 10 20) => 20

(определить (my-max3 x y z)
   (если (и (> x y) (> x z))
       Икс
       (если (> у z)
            у
            з)))
 

cond -- более общее условное выражение

. Общая форма специальной формы con:
(условие (test1 expr1)
      (тест2 выражение2)
      . ...
      (иначе выражение))
 
Как только мы находим тест, который оценивается как истинный, мы оцениваем соответствующее выражение и вернуть его значение. Остальные тесты не оценивается, а все остальные выражения не оцениваются. Если ни один из тестов не дает истинного результата, мы оцениваем exprn ("еще" часть) и вернуть его значение. (Вы можете опустить часть else, но это не хороший стиль.)
(определить (погода f)
   (cond ((> f 80) 'слишком жарко)
         ((> f 60) 'хорошо)
         ((

 

Стиль комментариев

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

Учебное пособие по схеме

Учебное пособие по схеме

(адаптировано с http://cs. wwc.edu/~cs_dept/KU/PR/Scheme.html)

Введение

Вы можете запустить Scheme в CCRMA, используя хитрость интерпретатора схемы или запустив snd (от xemacs, просто введите CTL-X CTLR-L)

Структура программ схемы

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

 (  аргументов имя_функции  )
 

Этот синтаксис отличается от обычного математического синтаксиса тем, что функция имя помещается в круглые скобки, а аргументы разделяются пробелы, а не запятые. Например, математическое выражение 3 + 4*5 записывается на схеме как

 (+ 3 (* 4 5))
 

Списки

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

минусы
принимает два аргумента и возвращает пару (список).
 (против '1 '2) это (1 . 2)
 (против '1' (2 3 4)) равно (1 2 3 4)
 (против '(1 2 3) '(4 5 6)) равно ((1 2 3) 4 5 6)
 

Первый пример — пара точек, остальные — списки.\marginpar{развернуть} Для реализации записей можно использовать либо списки, либо точечные пары.

автомобиль
возвращает первый элемент списка или пары точек.
 (автомобиль '(123 245 564 898)) 123
     (автомобиль '(первый второй третий)) первый
     (машина '(это (нет) сложнее)) это
 
cdr
возвращает список без его первого элемента или второго члена пунктирная пара.
 (cdr '(7 6 5)) есть (6 5)
     (cdr '(дождь идет каждый день)) есть (дождь каждый день)
     (cdr (cdr '(a b c d e f))) есть (c d e f)
     (car (cdr '(a b c d e f))) есть b
 
ноль?
возвращает \#t, если объект {\bf} является нулевым списком, (). Он возвращает нулевой список, (), если объект является чем-то еще.
список
возвращает список, составленный из его аргументов.
 (список 'а) есть (а)
     (список 'a 'b 'c 'd 'e 'f) есть (a b c d e f)
     (список '(a b c)) есть ((a b c))
     (список '(a b c) '(d e f) '(g h i)) есть ((a b c) (d e f) (g h i))
 
длина
возвращает длину списка.
 (длина '(1 3 5 9 11)) равна 5
 
реверс
возвращает список в обратном порядке.
 (обратное '(1 3 5 9 11)) равно (11 9 5 3 1)
 
добавить
возвращает объединение двух списков.
 (добавить '(1 3 5) '(9 11)) равно (1 3 5 9 11)
 

Функции

Выражения определения связывают имена и значения и имеют форму:

 (определить {\em id exp})
 

Вот пример определения.

 (определить пи 3.14)
 

Это определяет, что {\tt pi} имеет значение 3,14. это не задание оператор, так как его нельзя использовать для повторной привязки имени к новому значению.

Лямбда-выражения

Пользовательские функции определяются с помощью лямбда-выражений. лямбда выражения являются безымянными функциями вида:

 (лямбда ({\em id...}) {\em exp} )
 

Выражение {\tt (id…)} представляет собой список формальных параметров. и {\ тт exp} представляет тело лямбда-выражения.Вот два примера Применение лямбда-выражений.

 ((лямбда (х) (* х х)) 3) равно 9
     ((лямбда (x y) (+ x y)) 3 4) равно 7
 

Вот определение функции возведения в квадрат.

 (определить квадрат (лямбда (х) (* х х)))
 
Одно из различий между интерпретатором Guile и snd заключается в том, что display заменяется в snd на snd-print.

Введение в схему и ее реализацию

Введение в схему и ее реализацию — снова список Перейти к первому, предыдущему, следующему, последнему разделу, оглавлению.

Снова список

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

Схема>(определить firstfive '(один два три четыре пять))
#пустота
Схема>первая пятерка
(раз, два, три, четыре, пять)
 

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

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

Схема> (определить firstfive (перечислить «один», «два», «три», «четыре», «пять»))
#пустота
Схема>первая пятерка
(раз, два, три, четыре, пять)
 

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

Это работает независимо от того, является ли переменной с таким именем, потому что имена символов и имена переменных — совершенно разные вещи.

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

Неоднородные списки

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

Схема>(определить смешанные5' (один 2 (три и а) "четыре" 5))
#пустота
Схема>смешанный5
(один 2 (три и а) «четыре» 5)
 

Здесь мы создали смешанный список, первым элементом которого является символ, второе — целое число, третье — список символов, четвертое является строкой, а пятое — другим целым числом.(Технический термин для смешанного списка является «гетерогенным списком».)

Мы можем нарисовать это так:

       +-----+
смешанный5 | +--+-->+---+---+ +---+---+ +---+---+ +---+---+ +---+-- -+
       +-----+ | + | +-+->| + | +-+->| + | +-+->| + | +-+->| + | * |
                 +-+-+---+ +-+-+---+ +-+-+---+ +-+-+---+ +-+-+---+
                   | | | | |
                  \|/ \|/ | \|/ \|/
                  один 2 | "четыре" 5
                                         |
                                        \|/
                                       +---+---+ +---+---+ +---+---+
                                       | + | +-+->| + | +-+->| + | * |
                                       +-+-+---+ +-+-+---+ +-+-+---+
                                         | | |
                                        \|/ \|/ \|/
                                       три и

 

Обратите внимание, что мы рисуем символы ( один , три , и , и a ) как простые последовательности символов. это просто рисунок соглашение. Они действительно объекты, как и пары. Мы рисуем струны аналогично, но с двойными кавычками вокруг них. Не дайте себя обмануть – эти также являются объектами в куче. Мы просто рисуем их таким образом, чтобы сохранить картинка от загромождения.

Операции со списками

Мы уже видели две процедуры обработки списков, которые вы будете часто использовать. вагон и cdr . машина принимает указатель на пару, а извлекает значение своего первого ( car ) поля. cdr дублирует указатель на пару и возвращает значение ее второго ( cdr ) поля.

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

Учитывая наш список, хранящийся в mixed5 , мы можем извлечь части список с использованием car и cdr .

Схема>(машина смешанная5)
один
Схема>(cdr смешанный5)
(2 (три и а) «четыре» пять)
 

Используя car и cdr несколько раз, мы можем извлечь вещи за пределами первого элемента. Например, взяв cdr из cdr списка пропускает первые два элемента и возвращает остальные:

Схема>(cdr (cdr смешанный5))
((три и а) "четыре" 5)
 

Взяв машину из того списка (то есть машину из cdr из cdr ) возвращает первый элемент в этом списке:

Схема>(вагон (cdr (cdrmixed5)))
(три и а)
 

Мы можем продолжать делать это, например, взяв второй элемент этого sublist, взяв машину своего cdr.

Схема>(автомобиль (cdr (автомобиль (cdr (cdrmixed5)))))
а также
 

Это становится утомительным и запутанным — слишком много вложенных процедур. которые делают слишком мало на каждом шаге, поэтому Scheme предоставляет несколько процедур которые выполняют две операции со списками сразу. Два самых важных кадр и кадр .

cadr берет car из cdr , что дает вам второй пункт в списке. cddr берет cdr из cdr , пропуская первые две пары в списке и возвращая остальную часть списка.

Это позволяет нам сделать то же самое, что мы сделали выше, немного более лаконично. и читаемо:

Схема>(кадр(автомобиль(кддр смешанный5)))
а также
 

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

Конечно, даже если Схема не предоставила cadr и cdr , вы можете сами написать их в терминах car и cdr :

(определить (кадр х)
   (автомобиль (cdr х)))

(определить (cddr x)
   (кдр (кдр х)))
 

Схема фактически предоставляет предопределенные операции со списками для всех комбинаций. до четырех автомобилей и cdr . Например, кададр берет кадр из кадра .(Схема именования что шаблон a и d отражает эквивалент вложенность вызовов car и cdr .)

Вы, вероятно, не захотите возиться с большинством из них, потому что имена не очень интуитивно понятны. Две процедуры, которые стоит знать это list-ref и list-tail .

(список-ссылка список n ) извлекает n -й элемент списка list , что эквивалентно n-1 приложения cdr , а затем автомобиль .Например, (ссылка-ссылка '(a b c d e) 3) эквивалентно (car (cdr (cdr '(a b c d e)))) , и возвращает d .)

По сути, вы можете индексировать список, как если бы это был массив, используя список-ссылка . (Разумеется, время доступа к элементу списка линейна по индексу элемента. Если вам нужно постоянное время доступ, вы можете использовать векторы, т. е. одномерные массивы.) Обратите внимание, что нумерация начинается с нуля, поэтому (list-ref lis 3) возвращает четвертый элемент lis .Это согласуется с индексация векторов, которые также отсчитываются от нуля, а также отражают количество cdr операций.

(конец списка список n ) пропускает первый n элементов списка и возвращает указатель на остальные, что эквивалентно к повторным применениям cdr . (Это стандартная схема R4RS, но не по схеме IEEE. Если ваша схема не предоставляет list-tail , вы можете легко написать свой собственный.)

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

Мы могли бы написать (car (cdr (car (cdr (cdr (car (cdr) (cdr (cdr foo))))))))) , но это очень тяжело читать.Если мы используем кадр , кадр и cadddr , мы можем сделать его более читабельным с помощью одной функции вызов на каждом уровне структуры: (cadr (caddr (cadddr foo))) . Но все же понятнее написать (ссылка-ссылка (ссылка-списка (ссылка-списка foo 4) 3) 2)

или (с отступом)

(ссылка-ссылка (ссылка-списка (ссылка-списка foo 4)
                    3)
          2)
 

list-ref и list-tail гораздо удобнее, чем такие вещи, как caddr , когда индексы в списке меняются при запуске время.Например, мы могли бы использовать индексную переменную i (или какое-то другое выражение, которое возвращает целое число), чтобы выбрать i -й член списка: (list-ref foo i) . Пишу это с car и cdr потребует записи цикла или рекурсия для выполнения n-1 cdr s и car .

================================================== ================
Это конец Hunk N

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

(Вернитесь НАЗАД, чтобы прочитать Hunk O, который начинается с раздела Tail Recursion (Hunk O).)


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

Простая схема: Введение в информатику, глава 4: Определение собственных процедур

В старые времена они «определяли процедуры» следующим образом. Схема Simply: Введение в информатику, глава 4: Определение собственных процедур
Схема Simple: Введение в информатику 2/e Copyright (C) 1999 MIT

Глава 4


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

Как определить процедуру

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

 (определить (квадрат x)
  (* х х))
 

(значение, возвращаемое , определить , может отличаться в зависимости от версия схемы, которую вы используете.Многие версии возвращают имя процедура, которую вы определяете, но другие возвращают что-то еще. Это не имеет значение, потому что когда вы используете , определите , вас не интересует возвращаемое значение, а скорее в том, что Scheme запоминает новое определение для дальнейшего использования.)

Это определение процедуры под названием квадрат . Квадрат принимает один аргумент, число, и возвращает квадрат этого числа. Как только вы определили квадрат , вы можете использовать его точно так же, как вы использовать примитивные процедуры:

 > (квадрат 7)
49

> (+ 10 (квадрат 2))
14

> (квадрат (квадрат 3))
81
 

Это определение процедуры состоит из четырех частей.Первым является слово определить , которое указывает, что вы что-то определяете. Второй и третье вместе в круглых скобках: имя, которое вы хотите дать процедура и имена, которые вы хотите использовать для ее аргументов. Этот расположение было выбрано дизайнерами Схемы, потому что оно похоже на форма, в которой будет вызываться процедура. То есть (квадрат х) выглядит как как (квадрат 7) . Четвертая часть определения — это тело : выражение, значение которого обеспечивает возвращаемое функцией значение.

Специальные формы

Определение является специальной формой , исключением из правило оценки, о котором мы говорили. [1] Обычно выражение представляет собой вызов процедуры, поэтому общее правило состоит в том, что Scheme сначала вычисляет все подвыражения, а затем применяет результирующую процедуру к результирующим значениям аргументов. То особенность специальных форм в том, что схема не оценивает все подвыражения. Наоборот, каждая особая форма имеет свою особую правило оценивания.Например, когда мы определили квадрат , нет оценивалась часть определения: не квадрат , не х , а не (* х х) . Не имеет смысла вычислять (квадрат x) . потому что вы не можете вызвать процедуру квадрат до того, как определите ее!

Можно было бы описать специальные формы, используя следующую модель: «Некоторые процедуры хотят, чтобы их аргументы не оценивались, и Scheme распознает их. После воздержания от оценки определите аргументы , для например, Scheme вызывает процедуру определения с теми неоцененными аргументы. ” Но на самом деле конструкторы Схемы предпочли подумать об этом по-другому. Вся специальная форма, начинающаяся с , определяет , является просто совершенно разные вещи, чем вызов процедуры. В схеме есть нет процедуры с именем определить . На самом деле определяют, это не имя вообще ни о чем:

 > +
#<ПЕРВИЧНАЯ ПРОЦЕДУРА +>

> определить
ОШИБКА - НЕДЕЙСТВИТЕЛЬНЫЙ КОНТЕКСТ ДЛЯ KEYWORD DEFINE
 

Тем не менее, в этой книге, если только это не очень важно сделать различия, мы будем говорить так, как если бы существовала процедура, называемая , определить .Например, мы поговорим о « определить аргументы » и «значение возвращаемый определить ” и “вызов определить “.

Функции и процедуры

На протяжении большей части этой книги наши процедуры будут описывать процессы, которые вычислить функций. Функция представляет собой связь между некоторыми значениями вы уже знаете, и новое значение, которое вы хотите узнать. Например, Функция квадрат принимает число, например 8, в качестве входного значения и возвращает другое число, в данном случае 64, в качестве выходного значения.Функция во множественном числе принимает существительное, например «компьютер», и возвращает другое. слово, “компьютеры” в этом примере. Технический термин для функции входное значение является его аргументом . Функция может принимать более одного аргумент; например, функция остатка принимает два аргумента, например 12 и 5. Он возвращает одно значение, остаток от деления первого аргумент вторым (в данном случае 2).

Ранее мы говорили, что процедура — это «описание процесса, с помощью которого компьютер может получить некоторый результат, который нам нужен.Что мы подразумеваем под процессом ? Рассмотрим эти два определения:

f ( x )=3 x +12
г ( x )=3( x +4) Два определения требуют разных арифметических операций. Для Например, чтобы вычислить f (8), мы должны умножить 8 на 3, а затем добавить к результату 12. Чтобы вычислить г (8), мы должны прибавить 4 к 8, а затем умножить результат на 3. Но мы получите тот же ответ, 36, в любом случае. Эти два уравнения описывают разные процессов, , но они вычисляют одну и ту же функцию . Функция это просто связь между начальным значением (значениями) и результирующим значение, независимо от того, как этот результат вычисляется. В схеме мы могли бы сказать
 (определить (ф х)
  (+ (* 3 х) 12))

(определить (г х)
  (* 3 (+ х 4)))
 

, и мы бы сказали, что f и g — это две процедуры, которые представляют одну и ту же функцию.

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

Алабама    Монтгомери
Аляска    Джуно
Аризона    Феникс
Арканзас    Литл-Рок
Калифорния    Сакраменто
   …
Эта таблица представляет функцию государственного капитала; мы не показали все строки полной таблицы, но мы смогли. Есть только конечное количество штатов США. Числовые функции также могут быть представлены графиками, , как вы, вероятно, учили в старшей школе по алгебре. В этой книге наш основное внимание уделяется представлению функций процедурами. Единственная причина чтобы показать вам этот пример таблицы, нужно пояснить, что мы имеем в виду, когда говорим что функция представлена ​​процедурой , а не функция это процедура.

Мы скажем «процедура f », когда хотим обсудить операции мы говорим Схеме выполнить.Мы скажем, что «функция, представленная f », когда наше внимание сосредоточено на возвращаемом значении, а не на на механизме. (Но мы часто будем сокращать эту длинную вторую фразу с “функция f “, если контекст не является особенно сбивает с толку.)[2]

Имена аргументов и значения аргументов

— Длинный, — сказал Рыцарь, — но очень, очень красивый. Все, кто слышит, как я ее пою — либо слезы глаза, иначе. ..

“Или что еще?” сказала Алиса, потому что Рыцарь сделал внезапную паузу.

«А иначе, знаешь ли. Песня называется « Глаза пикши». ’ ”

“О, это название песни, не так ли?” Алиса сказала, пытаясь почувствовать интересно.

— Нет, ты не понимаешь, — сказал Рыцарь с легким раздражением. «Так называется номер . Имя на самом деле « Старик». Пожилой мужчина. &rsquo ”

«Тогда я должен был сказать: «Вот как называется песня »?» Алиса поправила себя.

«Нет, не надо; это совсем другое! Песня называется &lsquo способов и средств &rsquo: но это только то, что называется, ты знать!”

“Ну, тогда что песня?” — сказала Алиса, которая к этому времени совершенно сбит с толку.

“Я шел к этому,” сказал Рыцарь. «Песня на самом деле &lsquo A-sitting On A Gate ’: и мелодия моего собственного изобретения».

Льюис Кэрролл, Зазеркалье и что Алиса найдена там

Обратите внимание, что когда мы определили процедуру квадрата , мы дали имя, x , для ее аргумента. Напротив, когда мы вызвали в квадрате мы предоставили значение для аргумента (например, 7 ). Слово x является «заполнителем» в определении, которое означает любое значение, которое вы используете при вызове процедуры. Таким образом, вы можете прочитать определение в квадрате : «Для того, чтобы в квадрате число, умножьте это число на это число. ” Имя x занимает место конкретного числа, которое вы имеете в виду.

Убедитесь, что вы понимаете разницу между определением процедуры и называя это. Процедура представляет собой общую технику, которую можно применять ко многим конкретным случаям. Мы не хотим встраивать какой-либо конкретный случай в определение процедуры; мы хотим, чтобы определение выражало общую природу техника. Вам бы не понадобилась процедура, которая знает только, как принимать квадрат 7. Но когда вы на самом деле используете в квадрате , у вас есть чтобы быть точным в отношении того, какое число вы возводите в квадрат.

Имя для имени аргумента (фух!) — это формальный параметр. В нашем примере квадрат , x является формальным параметром. (Вы можете услышать, как люди говорят либо «формальный», в одиночку или только “параметр”, когда им лень.) технический термин для фактического значения аргумента – фактический аргумент . В случае, как

 (квадрат (+ 5 9))
 

вы можете отличить фактическое выражение аргумента (+ 5 9) от фактического значения аргумента 14.Большую часть времени это совершенно ясно что вы имеете в виду, и вы просто говорите “аргумент” для всех этих вещей, но прямо сейчас, когда вы изучаете эти идеи, важно уметь говорить точнее.

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

 (определить (ф а б)
  (+ (*3 а) б))

> (ф 5 8)
23

> (ф 8 5)
29
 

Процедура как обобщение

Какое среднее значение между 17 и 25? Чтобы ответить на этот вопрос, вы можете добавить два числа, получится 42, и разделим на два, получим 21. Вы могли бы спросить Схема, чтобы сделать это для вас:

 > (/ (+ 17 25) 2)
21
 

Какое среднее значение между 14 и 68?

 > (/ (+ 14 68) 2)
41
 

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

 (/ (+ ______ ______ ) 2)
 

к Схеме.

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

 (определить (среднее а б)
  (/ (+ а б) 2))
 

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

 > (в среднем 27 4)
15.5
 

Это пример того, что мы имели в виду, когда определяли «абстракция» как замечание паттерна и присвоение ему имени. Это не так уж отличается от именования таких шаблонов на английском языке; когда кто-то придумал название «средний», это было, наверное, после заметив, что часто было полезно найти значение на полпути между два других значения.

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

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

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

Компонуемость

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

 > (среднее (+ 10 8) (* 3 5))
16,5

> (в среднем (в среднем 2 3) (в среднем 4 5))
3,5

> (кв.м. (в среднем 143 145))
12
 

Любое возвращаемое значение может использоваться как самоцель, так как возвращаемое значение значение из sqrt использовалось в последнем из этих примеров, или оно может передать аргумент другой процедуре в качестве возвращаемого значения из * использовалось в первом из этих примеров.

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

Модель на замену

Мы уделили большое внимание деталям формальных параметров и фактических аргументы, но мы немного махнули рукой[3] на вопрос о том, как процедура на самом деле вычисляет значение, когда вы ее вызываете.

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

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

 (определить (квадрат x)
  (* х х))
 

, то тело квадрата равно (* x x) .Когда ты хочешь знать квадрат конкретного числа, как в (квадрат 5) , Схема заменяет 5 на x везде в теле квадрата и оценивает выражение. Другими словами, схема принимает

 (* х х)
 

затем делает замену, получая

 (* 5 5)
 

, а затем вычисляет это выражение, получая 25.

Если вы просто наберете (* x x) в Scheme, вы получите сообщение об ошибке жаловаться, что x ничего не значит. Только после замены становится ли это осмысленным выражением.

Кстати, когда мы говорим о «замещении тела», мы не имеем в виду что определение процедуры изменено каким-либо необратимым образом. Тело процедура не меняется; происходит, как мы говорили ранее, схема создает новое выражение, похожее на тело, за исключением замены.[4]

Есть людишки которые специализируются на квадрате , как и там это маленькие люди, специализирующиеся на + и *.Разница в том, что маленькие человечки, выполняющие примитивные процедуры, могут выполнять работу «по-своему». голова”, все сразу. Маленькие люди, выполняющие пользовательские процедуры должны пройти через этот бизнес замены, о котором мы говорим здесь. Затем они нанимают других маленьких людей, чтобы они помогли оценить получившееся выражение, точно так же, как Алонзо нанимает людей, чтобы они помогали ему оценивать выражения, которые вы вводите непосредственно в Схему.

Допустим, Сэм, маленький человек, который специализируется на квадрате , был попросили вычислить (квадрат 6) . Сэм производит замену и осталось с выражением (* 6 6) для оценки. Затем Сэм нанимает Тессу, специалист по умножению, чтобы вычислить это новое выражение. Тесса говорит Сэму что ее ответ равен 36, и, поскольку умножение — это вся проблема решить, это тоже ответ Сэма.

Вот еще пример:

 (определить (гипотенуза a b)
  (квадрат (+ (квадрат а) (квадрат б))))

> (гипотенуза 5 12)
 

Предположим, что Алонзо нанимает Гарри для вычисления этого выражения.Сначала Гарри должен подставить фактические значения аргументов (5 и 12) в тело гипотенуза :

 (квадрат (+ (квадрат 5) (квадрат 12)))
 

Теперь он оценивает это выражение так же, как его оценивал бы Алонзо. если вы набрали его в приглашении Scheme. То есть Гарри нанимает четырех маленьких человек: один sqrt эксперт, один + эксперт и два sqrt эксперты.[5] В частности, некоторые небольшие человек должен вычислить (квадрат 5) , подставив 5 вместо x в тело квадрат , как в предыдущем примере. Точно так же мы замените 12 на x , чтобы вычислить (квадрат 12) :

 (гипотенуза 5 12) ; подставить в тело ГИПОТЕНУЗЫ
(квадрат (+ (квадрат 5) (квадрат 12))) ; заменяет (КВАДРАТ 5)
         (* 5 5)
         25
(квадрат (+ 25 (квадрат 12))) ; заменяет (КВАДРАТ 12)
                    (* 12 12)
                    144
(кв.(+ 25 144))
      (+ 25 144) ; объединить результаты, как и раньше
      169
(кв. 169)
13
 

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

Ловушки

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

 (определить (сумма квадратов x y) ;; неправильно!
  (квадрат х)
  (квадрат у))
 

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

 (определить (сумма квадратов x y)
  (+ (квадрат х)
     (квадрат у)))
 

Еще одна ловушка связана с тем, что считается, что вызов процедуры изменяет значение параметра. Вот ошибочная программа, которая должна вычислять функция, описанная f ( x )=3 x +10:

 (определить (f x) ;; неправильно!
  (* х 3)
  (+ х 10))
 

Опять же, первое выражение не действует, и Scheme просто вернуть значение x +10.[6]

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

 (определить (квадрат x)
  (* х х))

(определить (квадрат площади) ;; неправильно!
  (квадратный квадрат))
 

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

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

Аналогичная проблема с конфликтами имен возникает, если вы пытаетесь использовать ключевое слово (имя специальной формы, например, определить ) как какое-либо другое имя — либо формальный параметр, либо имя процедура, которую вы определяете. Мы перечисляем это отдельно, потому что результат, скорее всего, будет другим. Вместо того, чтобы получить неправильное значение заменены, как указано выше, вы, вероятно, увидите специальное сообщение об ошибке по пунктам «неправильное использование ключевого слова.”

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

 (определить (f (+ 3 x) y) ;; неправильно!
  (* х у))
 

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

Сверлильные упражнения

4.1   Рассмотрите эту процедуру:

 (определить (хо-гум х у)
  (+ х (* 2 года)))
 

Показать замену, которая происходит при оценке

 (гом 8 12)
 

4. 2   С учетом следующей процедуры:

 (определить (зевок х)
  (+ 3 (* х 2)))
 

список всех маленьких людей, которые участвуют в оценке

 (зевок (/ 8 2))
 

(Назовите их имена, их специальности, их аргументы, кто их нанимает, и что они делают со своими ответами.)

4.3   Вот несколько определений процедур. Для каждого из них опишите функцию в English, покажите пример вызова и покажите результат этого вызова.

 (определить (f x y) (- y x))

(определить (тождество х) х)

(определить (три х) 3)

(определить (семь) 7)

(определить (магическое n)
  (- (/ (+ (+ (*3 н)
              13)
           (- п 1))
        4)
     3))
 

Реальные упражнения

4.4   Каждое из следующих определений процедур содержит какую-либо ошибку.Скажите, что не так и почему, и исправьте это:

 (определить (сфера-объем r)
  (* (/ 4 3) 3.1415)
  (* р р р))

(определить (следующий х)
  (х + 1))

(определить (квадрат)
  (* х х))

(определить (треугольник-площадь треугольника)
  (* 0,5 высоты основания))

(определить (сумма квадратов (квадрат x) (квадрат y))
  (+ (квадрат x) (квадрат y)))
 

4,5   Напишите процедуру преобразования температуры из градусов Фаренгейта в градусы Цельсия и другой, чтобы преобразовать в другом направлении. Две формулы F = 9 / 5 C +32 и C +32 и C = 5 / 9 ( F -32)

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

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

4.8   “Научная нотация” — это способ представления очень маленьких или очень больших числа, комбинируя число среднего размера со степенью 10.Например, 5×10 7 представляет число 50000000, а 3,26×10 -9 представляет 0,00000000326 в экспоненциальном представлении. Написать процедуру научный , который принимает два аргумента, число и показатель степени 10, и возвращает соответствующее значение:

 > (научный 7 3)
7000

> (научный 42 -5)
0,00042
 

Некоторые версии Схемы представляют дроби в форме a / b , и некоторые используют научную запись, поэтому вы можете увидеть 21/50000 или 4.2Е-4 в результате последнего примера вместо 0,00042 , но это такое же значение.

(Более сложная проблема для горячих точек: можете ли вы написать процедуры, которые идут в другое направление? Так что у вас будет

 > (научный коэффициент 7000)
7

> (научный показатель 7000)
3
 

Вам могут пригодиться примитивные процедуры log и floor .)

4.9   Определить процедуру скидка , которая принимает два аргумента: начальная цена и процентная скидка.Он должен вернуть новую цену:

 > (скидка 10 5)
9. 50

> (скидка 29,90 50)
14,95
 

4.10   Напишите процедуру для расчета чаевых, которые вы должны оставить в ресторане. Это должен принимать общий счет в качестве аргумента и возвращать сумму наконечник. Он должен дать чаевые на 15%, но он должен уметь округлять, чтобы общая сумма денег, которую вы оставляете (чаевые плюс первоначальный счет), представляет собой целое число долларов. (Используйте процедуру потолка для округления.)

 > (наконечник 19.98)
3.02

> (совет 29.23)
4,77

> (совет 7.54)
1,46
 

[1] Технически весь выражение (define (квадрат x) &hellip) — это специальная форма; само слово , определяющее , называется ключевым словом . Но на самом деле лиспийцы почти всегда забывают об этом различии и говорят: « определяет как особая форма», так же, как мы сделали здесь. Слово «форма» — архаичное синоним слова «выражение», поэтому «особая форма» просто означает «особая форма». выражение.”

[2] Кроме того, иногда мы будем использовать термины «домен» и “диапазон”, когда мы говорим о процедурах, хотя технически только функции имеют домены и диапазоны.

[3] Знаешь, это когда вы машете руками в воздухе вместо того, чтобы объяснить, что вы иметь в виду.

[4] Вы можете подумать, что это скорее неэффективный способ делать что-то — все это копирование и замена перед тем, как вы на самом деле может вычислить что угодно. Возможно, вы боитесь, что ваша Схема в результате программы будут работать очень медленно.Не волнуйтесь. Это реально происходит по-разному, но эффект тот же, за исключением скорость.

[5] Пока мы не начали определять наши собственные процедуры в этом глава, все маленькие люди были наняты Алонзо, потому что все выражения вводились непосредственно в приглашение схемы. Теперь выражения могут исходить из органов процедур, и таким людям нужно было вычисления этих выражений наняты маленьким человеком, который вычисляет та процедура. Заметьте также, что каждый маленький человек отчитывается перед . другой маленький человек, не обязательно тот, кто нанял ее.В в этом случае, если Гарри наймет Шари за sqrt , Пола за + и Слима и Сидней за два квадратных с, то Слим отчитывается перед Полом, а не перед Гарри. Только Шари подчиняется непосредственно Гарри.

[6] Это особенно проблематично для людей кто раньше программировал на таких языках, как Pascal или BASIC, где вы говорите что-то как “ X = X * 3 ” все время.

(обратно к оглавлению)

ЗАДНЯЯ ЧАСТЬ резьба главы СЛЕДУЮЩАЯ

Брайан Харви, бх@кс.berkeley.edu

Простая схема: Введение в информатику, глава 8: Функции высшего порядка

Превращение функциональных машин в орала Схема Simply: Введение в информатику, глава 8: Функции высшего порядка
Схема Simple: Введение в информатику 2/e Copyright (C) 1999 MIT

Глава 8


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

Вы можете использовать функцию first , чтобы найти первую букву слова. Что делать, если вы хотите найти первые буквы нескольких слов? Ты сделал это в первой главе, как часть процесса поиска акронимов.

Чтобы начать с простого случая, предположим, что у вас есть два слова (то есть предложение длины два). Вы можете применить процедуру first к каждому из них и объединить результаты:

 (определить (отправлено два первых)
  (se (первый (первый отправленный))
      (первая (последняя отправленная))))
 
> (Два первых' (Джон Леннон))
(Дж Л)
 
> (Два первого" (Джордж Харрисон))
(Г Н)
 
Точно так же вот версия для трех слов:
 (определить (отправлено три первых)
  (se (первый (первый отправленный))
      (первый (первый (бф отправил)))
      (первая (последняя отправленная))))
 
> (три первых '(Джеймс Пол Маккартни))
(JPM)
 
Но такой подход стал бы утомительным, если бы у вас было предложение из пяти слов. слова — вам пришлось бы писать процедуру специально для случая именно пять слов, и эта процедура будет иметь пять отдельных подвыражений для извлечь первое слово, второе слово и так далее.Кроме того, вы не нужна отдельная процедура для каждой длины предложения; вам нужна одна функция это работает независимо от длины предложения. Используя имеющиеся у вас инструменты уже узнал об этом, единственный возможный способ сделать это было бы довольно отвратительный:
 (определить (отправлены первые письма)
  (cond ((= (количество отправлено) 1) (первый отправлен))
        ((= (количество отправлено) 2) (два первых отправлено))
        ((= (количество отправлено) 3) (три первых отправлено))
        … и так далее …))
 

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

Каждый Чтобы написать лучшую процедуру для первой буквы любой длины, вы должны уметь сказать “применить функцию сначала до каждые слов в предложении, нет независимо от того, насколько длинным является предложение. ” Схема предоставляет способ сделать это:[1]
 (определить (отправлены первые письма)
  (каждый первый отправленный))
 
> (первые буквы '(вот и солнце))
(Х С Т С)
 
> (первые буквы '(люси в небе с бриллиантами))
(Л И Т С Ш Д)
 
Каждый принимает два аргумента.Второй аргумент — это предложение, но во-первых, что-то новое: процедура , используемая в качестве аргумент другой процедуры.[2] Обратите внимание, что вокруг слова first нет круглых скобок. в теле первых букв ! К настоящему времени вы привыкли видеть круглые скобки всякий раз, когда вы видите имя функции. Но скобки указать вызов функции, и мы не вызываем сначала здесь. Мы используем first , саму процедуру в качестве аргумента. до каждые .
 > (все до последнего '(пока моя гитара нежно плачет))
(Е, Р, И, С)
 
> (каждый - '(4 5 7 8 9))
(-4 -5 -7 -8 -9)
 
В этих примерах используется каждые с примитивными процедурами, но Конечно, вы также можете определить свои собственные процедуры и применять их к каждые . слово предложения:
 (определить (существительное во множественном числе)
  (если (равно? (последнее существительное) 'y)
      (слово (бл существительное) 'ies)
      (слово существительное)))
 
> (каждое множественное число «(битл, черепаха, холли, кинк, зомби))
(BEATLES TURTLES HOLLIES KINKS ZOMBIES)
 

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

 (определить (двойная буква) (слово буква буква))

> (каждая двойная девушка)
(ГГ II РР ЛЛ)

> (каждый квадрат 547)
(25 16 49)
 

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

 (определить (отправить первые два wd)
  (se (первый wd) (первый (bf wd))))

> (каждый посланный из первых двух '(внутренний свет))
(Т Х И Н Л Я)

> (каждая отправка первых двух '(скажи мне, что ты видишь))
(Т Е М Е В Х И О С Е)

> (определить (g wd)
    (se (слово 'с wd) 'вы))

> (каждый г '(вход))
(ВНУТРИ ВАС БЕЗ ВАС)
 

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

Пауза для размышлений

Ранее мы использовали метафору «функциональной машины» с бункер наверху, в который мы сбрасываем данные, и желоб наверху дно, с которого падает результат, как из мясорубки. Хорошо, каждый – это функциональная машина, в бункер которой мы бросаем другой функциональная машина! Вместо мясорубки у нас металлическая мясорубка.[3]

Видишь, какая захватывающая идея? Мы привыкли к думать о числах и предложениях как о «реальных вещах», тогда как функции меньше похожи на вещи и больше на деятельность. По аналогии подумайте о приготовлении пищи. Настоящая еда — это мясо, овощи, мороженое, и так далее. Вы не можете съесть рецепт, который аналогичен функция. Рецепт должен применяться к ингредиентам, а результат выполнения рецепта является съедобным блюдом. Было бы странно если в рецепте использовались другие рецепты в качестве ингредиентов: «Разогрейте духовку до 350 и вставьте Joy of Cooking. ” Но в Схеме мы может сделать именно это.[4]

Готовить по кулинарной книге необычно, но общий принцип — нет. В некоторых случаях мы относимся к рецептам как к вещам, а не как к алгоритмы. Например, люди пишут рецепты на карточках и кладут их в папку с файлами рецептов. Затем они выполняют такие операции, как поиск для конкретного рецепта, сортировка рецептов по категориям (основное блюдо, десерт и т. д.), копирование рецепта друга и т. д. Одинаковый рецепт — это и процесс (когда мы с ним готовим), и объект процесса (когда мы его регистрируем).

Хранить

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

Например, функция keep принимает предикат и предложение как аргументы. Возвращает предложение, содержащее только слова аргумента предложение, для которого сказуемое истинно.

 > (остаться равным? '(1 2 3 4 5))
(2 4)
 
> (определить (оканчивается-e? слово) (равно? (последнее слово) 'e))
 
> (оставь концы-э?' (пожалуйста, положите салями над синим слоном))
(ПОЖАЛУЙСТА, НАД СИНИМ)
 
> (сохранить номер? '(1 после 909))
(1 909)
 

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

 > (сохранить номер? 'zonk23hey9)
239

> (определить (гласная? буква) (член? буква' (а е и о ю)))

> (сохранять гласную? «свинки»)
ИИЭ
 

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

 (определить (настоящее слово? wd)
  (не (член? wd '(а в и для с))))

> (держать реальное слово? '(люси в небе с бриллиантами))
(ЛЮСИ СКАЙ ДАЙМОНДС)

> (каждый первый (держать реальное слово?'(люси в небе с бриллиантами)))
(Л С Д)
 

Накопить

В каждые и сохраняют , каждый элемент второго аргумента вносит независимо в общий результат. То есть каждые и сохраняют , применяя процедуру к одному элементу за раз.То общий результат представляет собой набор отдельных результатов без взаимодействия между элементами аргумента. Это не позволяет нам говорить такие вещи, как «Добавить все числа в предложении», где желаемый результат — функция всего аргумента предложения, взятого в целом. Мы можем сделать это с процедура с именем накапливает . Накопление выполняет процедуру и предложение в качестве его аргументов. Он применяет эту процедуру к двум словам приговора. Затем применяется процедура к результату мы получили еще и еще один элемент предложения, и так далее.Он заканчивается, когда все слова предложения объединяются в один результат.

 > (накопить + '(6 3 4 -5 7 8 9))
32
 
> (накопить слово '(a c l u))
ACLU
 
> (накопить максимум '(128 32 134 136))
136
 
> (определить (перенести слово1 слово2)
    (слово слово1 '- слово2))
 
> (накопить дефис '(ob la di ob la da))
ОБ-ЛА-ДИ-ОБ-ЛА-ДА
 

(Во всех наших примерах в этом разделе второй аргумент содержит не менее двух элементов. В разделе “подводные камни” в конце в этой главе мы обсудим, что происходит с меньшими аргументами.)

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

 > (накопить + 781)
16

> (накопить предложение 'колин)
(К О Л И Н)
 

Объединение функций высшего порядка

Что, если мы хотим сложить все числа в предложении, но проигнорируем слова? это не числа? Сначала мы сохраняем числа в предложении, затем мы накапливаем результат с + . На схеме проще сказать:
 (определить (отправлены добавочные номера)
  (накопить + (сохранить номер? отправлено)))
 
> (добавить цифры '(4 говорящие птицы, 3 французские курицы, 2 горлицы))
9
 
> (добавить цифры'(1 за деньги 2 за шоу 3 чтобы приготовиться
и 4 осталось))
10
 

У нас также достаточно инструментов, чтобы написать версию процедуры count , который находит количество слов в предложении или количество букв в слово.Во-первых, мы определим процедуру always-one , которая возвращает 1 no. независимо от того, каковы его аргументы. Мы будем 90 141 каждый всегда один 90 142 из-за нашего спора предложение,[5] которое приведет к предложению как столько, сколько слов было в исходном предложении. Тогда мы можем использовать накапливает с помощью + , чтобы сложить единицы. это немного обходной подход; позже мы увидим более естественный способ найти счет в предложении.

 (определить (всегда один аргумент)
  1)

(определить (количество отправленных)
  (накопить + (каждому всегда-по одному отправленному)))

> (считай '(продолжение истории Билла о бунгало))
6
 
Теперь вы можете понять процедуру аббревиатуры из главы 1:
 (определение (аббревиатура)
  (накопить слово (каждое первое (сохранить реальное слово? фраза))))

> (аббревиатура '(компьютер с сокращенным набором команд))
РИСК

> (аббревиатура '(структура и интерпретация компьютерных программ))
SICP
 

Выбор правильного инструмента

До сих пор вы видели три функции высшего порядка: каждые , сохраняет , а накапливает . Как вы решаете, какой из них использовать для решения конкретной проблемы?

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

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

Накопление преобразует все слово или предложение в один результат комбинируя все элементы каким-либо образом.

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

Вот еще один способ сравнить эти три функции более высокого порядка:

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

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

 > (каждая двойная девушка)
(ГГ II РР ЛЛ)

> (se (двойной 'g)
      (двойное «я»)
      (двойной р)
      (двойной л))
(ГГ II РР ЛЛ)
 

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

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

 > (остаться равным? '(1 2 3 4 5))
(2 4)

> (se (если (даже? 1) 1 '())
      (если (даже? 2) 2'())
      (если (даже? 3) 3'())
      (если (даже? 4) 4'())
      (если (даже? 5) 5'()))
(2 4)
 

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

 > (накопить слово '(a c l u))
ACLU

> (слово 'а (слово 'с (слово 'л'у)))
ACLU
 

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

Первоклассные функции и первоклассные предложения

Если Scheme (или любой диалект Lisp) — ваш первый язык программирования, наличие процедур, обрабатывающих целые предложения сразу, может показаться не таким большое дело. Но если вы раньше программировали на каком-то более низком языке, вы возможно, вы привыкли писать что-то вроде первых букв в виде цикла , в котором у вас есть некоторая переменная с именем I , и вы выполняете некоторые последовательность шагов для I=1 , I=2 и так далее, пока не дойдете до N , количества элементов. Использование функций высшего порядка позволяет выражайте эту проблему сразу, а не в виде последовательности событий. Один раз вы привыкли к мышлению на Лиспе, вы можете сказать себе “просто возьми каждые первые предложения», и это похоже на один шаг, не сложная задача.

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

Во-вторых, функции тоже первоклассные. Это позволяет нам писать процедура, подобная pigl , которая применяется к одному слову, а затем объедините это с через каждые , чтобы перевести целое предложение на свиную латынь. Если бы в Scheme не было первоклассных функций, у нас не было бы универсальных функций. такие инструменты, как , сохраняют и каждые , потому что мы не могли сказать, какой функция распространения на все предложение. Позже вы увидите, что без каждый все равно можно было бы написать конкретный pigl-sent процедуру и отдельно написать процедуру первых букв . Но возможность использовать процедуру в качестве аргумента для другой процедуры позволяет нам обобщить идею «применить эту функцию к каждому слову предложение.”

Повторный

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

В следующем примере процедура , повторенная , возвращает процедуру:

 > ((повторяется bf 3) '(она вошла через окно ванной))
(ЧЕРЕЗ ОКНО ВАННОЙ)
 
> ((повторяющееся множественное число 4) «компьютер»)
КОМПЬЮТЕРЫSSSS
 
> ((повторяется квадрат 2) 3)
81
 
> (определить (двойная отправка)
    (сэ отправлено отправлено))
 
> ((повторяется дважды 3) '(банан))
(БАНАН БАНАН БАНАН БАНАН БАНАН БАНАН БАНАН БАНАН БАНАН)
 
Процедура , повторенная , принимает два аргумента, процедуру и число. и возвращает новую процедуру.Возвращаемая процедура — это та, которая вызывает оригинальная процедура неоднократно. Например, (повторяется bf 3) возвращает функцию, которая принимает первое из но сначала его аргумент. Обратите внимание, что все наши примеры начинаются с двух открытых скобок. Если мы просто вызывали , повторяли в командной строке Scheme, мы возвращали процедуру, так:
 > (повторяется квадрат 4)
#<ПРОЦЕДУРА>
 
Процедура, которую мы получаем, сама по себе не очень интересна, поэтому мы вызываем его, например:
 > ((повторяется квадрат 4) 2)
65536
 
Чтобы понять это выражение, нужно хорошенько подумать над его два подвыражения.Два подвыражения? Потому что есть два открытых скобки рядом друг с другом, было бы легко проигнорировать одну из них и поэтому подумайте о выражении как имеющем четыре атомарных подвыражения. Но на самом деле их всего два. Значением первого подвыражения, (повторяющийся квадрат 4) , является процедура. Второй подвыражение 2 имеет в качестве значения число. Стоимость всего выражение происходит от применения процедуры к числу. Все это время мы говорили, что вы оцениваете составное выражение в двух шаги: Сначала вы оцениваете все подвыражения.Затем вы применяете первое значение, которое должно быть процедурой, к остальным значениям. Но до сих пор первым подвыражением всегда было одно слово, название процедуры. Теперь мы видим, что первое выражение может быть вызов функции более высокого порядка, как и любой из аргументов подвыражения могут быть вызовами функций. Мы можем использовать повторение для определения элемента , который возвращает определенный элемент предложения:
 (определить (элемент отправлен)
  (первый ((повторный бф(- н 1)) отправлен)))
 
> (п.1'(день из жизни))
А
 
> (п.4'(день из жизни))
НАШИ
 

Ловушки

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

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

 (определить (любые числа? отправлено) ;; неправильно!
  (накопить или (каждое число? отправлено)))
 

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

 > (предложение #T #F)
ОШИБКА: АРГУМЕНТ ДЛЯ ПРИГОВОРЕНИЯ НЕ СЛОВО ИЛИ ПРЕДЛОЖЕНИЕ: #F

> (каждое число? '(a b 2 c 6))
ОШИБКА: АРГУМЕНТ ДЛЯ ПРИГОВОРЕНИЯ НЕ СЛОВО ИЛИ ПРЕДЛОЖЕНИЕ: #T
 

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

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

 (определить (любые числа? отправлены)
  (не (пусто? (оставить номер? отправлено))))
 

Функция keep всегда возвращает результат одного и того же типа (т. е. слово или предложение) в качестве второго аргумента. Это имеет смысл, потому что если вы выбрав подмножество слов предложения, вы хотите получить предложение; но если вы выбираете подмножество букв слова, вы хочу слово. С другой стороны, каждый всегда возвращает предложение. Вы можете подумать, что будет иметь больше смысла каждые возвращать слово, когда его вторым аргументом является слово. Иногда — это , что вы хочется, но иногда нет. Например:

 (определить (цифра по буквам)
  (элемент (+ 1 цифра)
'(ноль один два три четыре пять шесть семь восемь девять)))

> (каждое заклинание-цифра 1971)
(ОДИН ДЕВЯТЬ СЕМЬ ОДИН)
 

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

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

Некоторые люди пытаются обойти это, говоря что-то вроде

 (каждый (частное 6) '(1 2 3)) ;; неправильно!
 

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

 (частное 6 1)
(частное 6 2)
(частное 6 3)
 

Но, конечно, то, что на самом деле делает Схема, всегда одно и то же. делает: оценивает выражения аргументов, а затем вызывает каждые . Так Схема попытается вычислить (частное 6) и выдаст сообщение об ошибке.

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

 (каждый (+ 3) '(1 2 3)) ;; неправильно!
 

Первый аргумент каждые в этом случае не является процедура, добавляющая 3″, но результат возвращается вызовом + с единственный аргумент 3 . (+ 3) возвращает число 3 , которое это не процедура. Таким образом, вы получите сообщение об ошибке типа «Попытка применить непроцедурный 3″.

Идея этой ошибки — поиск способа «специализировать» двухаргументная процедура с заранее заданным одним из аргументов — это на самом деле хороший. В следующей главе мы представим новый механизм что позволяет такую ​​специализацию.

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

 (определить (номер битла n)
  (если (или (< n 1) (> n 4))
      '()
      (item n'(джон пол джордж ринго))))

> (битл номер 3)
ДЖОРДЖ

> (битл-номер 5)
()

> (каждый битл-номер '(2 8 4 0 1))
(ПОЛ РИНГО ДЖОН)
 

Что случилось с 8 и 0 ? Представьте, что каждый не существует, и вам пришлось сделать это трудным путем:

 (se (битл-номер 2) (битл-номер 8) (битл-номер 4)
    (битл-номер 0) (битл-номер 1))
 

Используя замену результата, мы получили бы

 (se 'пол'() 'ринго'() 'джон)
 

, это всего лишь (ПОЛ РИНГО ДЖОН) .

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

 > (каждый парень '(ты мне нужен))
("" ЭЕД ОУ)
 

Предложение, возвращенное каждым , состоит из трех слов: пустое слово, eed и или .

Не путайте

 (первый '(один два три четыре))
 

с

 (каждый первый '(один два три четыре))
 

В первом случае мы применяем процедуру first к предложение; во втором мы применяем первый четыре раза, к каждому из четырех слов отдельно.

Что произойдет, если в качестве аргумента использовать однословное предложение или однобуквенное слово к накопить ? Он возвращает то слово или ту букву, даже не вызов заданной процедуры. Это имеет смысл, если вы используете что-то как + или макс в качестве аккумулятора, но это смущает

 (накопить se '(одно слово))
 

возвращает слово одно слово .

Что произойдет, если дать аккумулировать пустое предложение или слово? Accumulate принимает пустые аргументы для некоторых объединителей, но не для другие:

 > (накопить + '())
0

> (накопить максимум '())
ОШИБКА: НЕ МОЖЕТ НАКОПИТЬ ПУСТОЙ ВХОД С ЭТИМ ОБЪЕДИНИТЕЛЕМ
 

Комбайнеры, которые можно использовать с пустым предложением или словом, + , * , слово и предложение . Накопить чека специально для одного из этих объединителей.

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

 > (+)
0

> (макс.)
ОШИБКА: НЕДОСТАТОЧНО АРГУМЕНТОВ ДЛЯ #<ПРОЦЕДУРА>.
 

Accumulate фактически вызывает объединитель без аргументов чтобы узнать, какое значение вернуть для пустого предложения или слова.Мы хотели бы реализовать , накапливая , чтобы любой процедура, которая может быть вызвана без аргументов, будет принята как объединитель для накопления пустого предложения или слова. К сожалению, схема не дает программе возможности спросить: «Сколько аргументов будет у этой процедура accept?” Лучшее, что мы могли сделать, это построить конкретный набор объединители без аргументов в определение накапливают .

Не думайте, что возвращаемое значение для пустого аргумента всегда равно нулю или пустой.

 > (накопить * '())
1
 

Такое поведение объясняется тем, что любая работающая функция в этом случае без аргументов возвращает свой элемент идентификации . Что такое элемент идентичности? Функция + имеет элемент идентичности 0 , потому что (+ что угодно 0) возвращает что угодно. Точно так же пустое слово является элементом идентификации для слова . В общем, элемент идентичности функции обладает тем свойством, что когда вы вызываете функцию с элементом идентификации и чем-то еще, как аргументы, возвращаемое значение — это что-то еще.Это схема соглашения что процедура с элементом идентификации возвращает этот элемент при вызове без аргументов.[8]

Использование двух последовательных открывающих скобок для вызова процедуры возвращаемая процедурой, представляет собой странную нотацию:

 ((повторяется bf 3) 987654)
 

Не путайте это с похожим обозначением cond , в котором внешние круглые скобки имеют особое значение (разделение условия и условия ). Здесь скобки имеют свое обычное значение.Внутренний круглые скобки вызывают процедуру , повторяют с аргументами bf и 3 . Значение этого выражения является процедурой. У него нет name, но для целей этого абзаца давайте представим, что он называется bfthree . Тогда внешние скобки в основном говорят (bfthree 987654) ; они применяют безымянную процедуру к аргументу 987654 .

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

 (повторяется bf 3 987654) ;; неправильно
 

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

Сверлильные упражнения

8.1   Что возвращает Scheme в качестве значения каждого из следующих выражений? Разберитесь в этом сами, прежде чем пробовать на компьютере.

> (каждый последний '(алгебра фиолетовый спагетти помидор гну))

> (сохранить число? '(один два три четыре))

> (накопить * '(6 7 13 0 9 42 17))

> (член? 'h (держать гласную? '(th r o a t)))

> (каждый квадрат (остаться равным? '(87 4 7 12 0 5)))

> (накопить слово (сохранить гласную? (каждую первую '(и я ее люблю))))

> ((повторяющийся квадрат 0) 25)

> (каждый (повторяется бл 2) '(добрый день, солнышко))
 

8.2   Заполните пробелы в следующих взаимодействиях Схемы:

 > (______ гласная? 'день рождения)
Я

> (______ первый '(золотой сон))
(ГС)

> (______ '(золотой сон))
ЗОЛОТОЙ

> (______ ______ '(маленький ребенок))
(ЭД)

> (______ ______ (______ ______ '(маленький ребенок)))
ЭД

> (______ + '(2 3 4 5))
(2 3 4 5)

> (______ + '(2 3 4 5))
14
 

8.3   Опишите каждую из следующих функций на английском языке. Не забудьте включить описание домена и диапазона каждой функции.Будьте так же точны, как возможно; например, “аргумент должен быть функцией одного числового аргумент» лучше, чем «аргумент должен быть функцией».

 (определить (ф а)
  (держать даже? а))

(определить (гб)
  (каждый б '(голубая сойка путь)))

 
 (определить (h c d)
  (с (с д)))

(определить (т.е.)
  (/ (накопить + е) (посчитать е)))

накапливать

кв

повторный

(повторяется кв. 3)

(повторяется даже? 2)

(повторяется первые 2)

(повторяется (повторяется bf 3) 2)
 

Реальные упражнения

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

8.4   Напишите процедуру Choose-Beatles , которая принимает предикат в качестве своего аргумента и возвращает предложение только тех «Битлз» (Джон, Пол, Джордж и Ринго), которые удовлетворяют предикату. Например:

 (определить (окончание-гласный? wd) (гласный? (последний wd)))

(определить (четный счет? wd) (четный? (счет wd)))

> (выбрать-битлы заканчиваются-гласная?)
(ДЖОРДЖ РИНГО)

> (выбрать-битлы-четный счет?)
(ДЖОН ПОЛ ДЖОРДЖ)
 

8. 5   Напишите процедуру transform-beatles , которая принимает процедуру как аргумент, применяет его к каждому из Beatles и возвращает результаты в виде предложение:

 (определить (имя)
  (слово 'удивительное-имя))
 
 > (трансформация-битлы поражают)
(УДИВИТЕЛЬНЫЙ-ДЖОН, УДИВИТЕЛЬНЫЙ-ПОЛ, УДИВИТЕЛЬНЫЙ-ДЖОРДЖ
 УДИВИТЕЛЬНОЕ РИНГО)

> (трансформировать-битлов, но сначала)
(ОН АУЛ ЭОРГЕ ИНГО)
 

8.6   Когда вы разговариваете с кем-то по шумной радиосвязи, вы иногда нужно произнести слово по буквам, чтобы другой человек понял его.Но названия букв тоже не так легко понять, так что есть стандартный код, в котором каждая буква представлена ​​определенным словом, начинается с буквы. Например, вместо «Б» вы говорите «браво».

Напишите процедуру слов , которая принимает слово в качестве аргумента и возвращает предложение имен букв в слове:

 > (слова "кабина")
(ЧАРЛИ АЛЬФА БРАВО)
 

(Вы можете сами придумать названия букв или посмотреть стандартные, если хотите. )

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

8,7   [14,5][9] Напишите процедуру подсчета букв , которая берет предложение в качестве своего значения. аргумент и возвращает общее количество букв в предложении:

 > (счетчик букв '(фиксация отверстия))
11
 

8,8   [12,5] Напишите процедуру преувеличения , которая преувеличивает предложения:

 > (утрировать '(я съел 3 потстикера))
(Я СЪЕЛ 6 ПОСТСТИКЕРОВ)

> (утрировать '(здесь хорошо покушать))
(ЗДЕСЬ ОТЛИЧНО РАЗВЛЕЧАЕТСЯ ЧАУ)
 

Следует удвоить все числа в предложении и заменить «хороший» с «отличным», «плохой» с «ужасным» и все остальное, что вы можно подумать.

8.9   Какую процедуру можно использовать в качестве первого аргумента для каждого , чтобы для любое предложение, используемое в качестве второго аргумента, каждые возвращает это предложение?

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

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

8. 10   Написать предикат истинный для всех? , который принимает два аргумента: предикатная процедура и предложение. Он должен вернуть #t , если Аргумент predicate возвращает true для каждых слов в предложении.

 > (истинно для всех? даже? '(2 4 6 8))
#Т

> (верно для всех? четно? '(2 6 3 4))
#F
 

8.11   [12.6] Напишите процедуру GPA. Он должен принимать предложение оценок в качестве аргумента и вернуть соответствующий средний балл:

 > (гпа '(А А+ В+ В))
3.67
 

Подсказка: напишите вспомогательную процедуру базового класса , которая принимает оценка в качестве аргумента и возвращает 0, 1, 2, 3 или 4 и другой помощник процедура , модификатор класса , которая возвращает -0,33, 0 или 0,33, в зависимости от имеет ли оценка минус, плюс или ни то, ни другое.

8.12   [11.2] Когда вы преподаете урок, люди будут отвлекаться, если вы слишком часто говорите «гм». раз. Напишите число count-ums , которое подсчитывает количество раз “гм” появляется в предложении:

 > (кол-ум
   '(сегодня мы поговорим о функциональном программировании))
3
 

8.13   [11.3] Напишите процедуру phone-unspell , которая принимает записанную версию номер телефона, например POPCORN , и возвращает реальный номер телефона в этот случай 7672676 . Вам нужно будет написать вспомогательную процедуру, которая использует выражение 8-way cond для перевода одной буквы в цифра.

8.14   Напишите процедуру подслово , которая принимает три аргумента: a слово, номер начальной позиции и номер конечной позиции.Должно вернуть подслово, содержащее только буквы между указанными позиции:

 > (подслово «полиэтилен 5 8»)
ТОГДА
 

[1] Как и все процедуры в этой книге, которые имеют дело со словами и предложения, каждые и другие процедуры в этой главе являются частью наших расширений Scheme. Позже, в главе 17, мы ввести стандартные эквиваленты Схемы.

[2] Говорить о каждые утомительно. решение отличать функции от процедур, которые их реализуют.Является ли аргумент каждые функцией или процедурой? Если мы подумаем о каждый сам по себе как процедура, то есть если мы сосредоточимся на том, как делает свою работу — тогда, конечно, мы должны сказать, что она делает свою работу, неоднократно вызывая процедуру , которую мы предоставляем в качестве аргумента. Но это одинаково справедливо для нас обратить внимание на функцию, которую каждый процедура реализует, и эта функция принимает функций как аргументы.

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

[4] Некоторые рецепты могут включать другие рецепты, потому что они говорят что-то вроде «добавьте песто (рецепт на стр. 12).” Но это всего лишь композиция функций; результат процедуры песто используется в качестве аргумента к этому рецепту. То Рецепт песто сам по себе не является ингредиентом.

[5] Мы имеем в виду, конечно, «Мы будем вызывать каждые с процедура всегда-один и наше аргументное предложение в качестве двух ее аргументов.” После того, как вы какое-то время программируете компьютеры, такое злоупотребление Английский будет для вас естественным.

[6] Под «обычно» мы подразумеваем, что каждые наиболее часто используется с функцией-аргументом, которая возвращает одно слово. Если функция возвращает предложение, длина которого может быть не равна единице, тогда число слов в общем результате может быть что угодно!

[7] Как мы говорили в главе 4, специальные формы не процедуры и не являются первоклассными.

[8] Схема ПК возвращает ноль при вызове max без аргументов, но это неправильный ответ.Во всяком случае, ответ должен быть -∞.

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

(обратно к оглавлению)

ЗАДНЯЯ ЧАСТЬ резьба главы СЛЕДУЮЩАЯ

Брайан Харви, бх@кс.berkeley.edu

2.2 Простые определения и выражения

2.2 Простые определения и выражения

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

#lang ‹langname› ‹topform›*

, где ‹topform› является либо ‹topform› либо ‹topform› ‹выражение›. REPL также оценивает ‹topform›.

В спецификациях синтаксиса текст на сером фоне, например #lang представляет обычный текст. Должен появиться пробел между такими литералами и нетерминалами, как ‹id›, за исключением того, что пробел не требуется ни до, ни после (, ), [, или ].Комментарий, который начинается с участием ; и работает до конца строки, обрабатывается то же, что пробел.

Чтение комментариев в The Racket Reference содержит больше информации о различных формах комментариев.

Следуя обычным соглашениям, * в грамматике означает ноль или более повторений предыдущего элемента, + означает один или более повторений предыдущего элемента и групп {} последовательность как элемент для повторения.

2.2.1 Определения

Определение формы

Определения: определение (далее в этом руководстве) объясняет больше об определениях.

( define ‹id› ‹expr›)

связывает ‹id› с результатом ‹expr›, а

+

( ‹define ( ‹id*id›)

связывает первый ‹id› с функцией (также называемой процедура), которая принимает аргументы, названные остальными ‹id› с. В случае функции ‹expr›s являются телом функции. Когда функция вызывается, она возвращает результат последнее ‹выражение›.

Примеры:

(определить круг 3)             ; Определяет пирог до 3
(определить (Piece STR); определяет деталь как функция
(SUBLING STR 0 PIE)); одного аргумента
> Pie

3

3

3

> (Piece «Key Lime»)

«Ключ»

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

Примеры:

примеры:

3

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

примеры:

примеры:

> Piece

8

# <Процедура: Piece>

> Подстрока

# <Процедура: подстрока>

  • 8
  • > (Выпекание Apple »)

    ” Apple Pier “

    Racket Programmers предпочитают избегать побочные эффекты, поэтому определение обычно имеет только одно выражение в своем теле. Его важно, тем не менее, понимать, что разрешены множественные выражения в теле определения, потому что это объясняет, почему следующее Неправильная функция не включает его аргумент в своем результате:

    8

    “Jello”

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

    2.2.2 Замечание по коду отступов

    Разрывы строк и отступы не имеют значения для синтаксического анализа Racket программы, но большинство программистов Racket используют стандартный набор соглашений сделать код более читабельным. Например, тело определения обычно с отступом под первой строкой определения.Идентификаторы пишутся сразу после открывающей скобки без дополнительного пробела, и закрывающие круглые скобки никогда не располагаются на отдельной строке.

    DrRacket автоматически делает отступ в соответствии со стандартным стилем при вы вводите Enter в программе или выражении REPL. Например, если вы нажмите Enter после ввода (определить (приветствовать имя), затем DrRacket автоматически вставляет два пробела для следующей строки. Если вы измените регион кода, вы можете выбрать его в DrRacket и нажать Tab, и DrRacket изменит отступ кода (без вставки разрывов строк).Такие редакторы, как Emacs, предлагают режим Racket или Scheme с аналогичными отступами. служба поддержки.

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

    (define (вкус halhbakeВ других случаях где отступ может быть нормальным, а открывающая скобка не имеет совпадающих с закрывающими скобками, и рэкет, и DrRacket используют отступ источника, чтобы указать, где может отсутствовать скобка.

    2.2.3 Идентификаторы

    Синтаксис Racket для идентификаторов особенно либерален. За исключением специальные символы

    Идентификаторы и привязка (далее в этом руководстве) объясняет больше об идентификаторах.

       ( ) [ ] { } ” , ‘ ` ; # | \

    и за исключением последовательностей символов, которые делают числовые константы, почти любая последовательность непробельных символов образует <я бы>.Например, подстрока является идентификатор. Кроме того, добавление строки и a+b идентификаторы, в отличие от арифметических выражений. Вот несколько другие примеры:

    +
    целое число?
    Pass / Fail
    Hfuhruhurr & Uumellmahaye
    John-Jacob-Jingleheimer-Schmidt
    AB-C + 1-2-3
    scrbl")” x-source-pkg=”racket-doc” x-part-tag=”"Function_Calls__Procedure_Applications_"”> 2.2.4 Вызовы функций (процедуры приложений)

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

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

    ( ‹id› ‹expr›* )

    , где количество ‹expr›s определяет количество аргументы, передаваемые функции с именем ‹id›.

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

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

    4

    > (добавление строки “веревка” “бечевка” “пряжа”)  ; добавить строки

    “ropetwineyarn”

    > (подстрока “corduroys” 0 4)            ; извлечь подстроку

    “cord”

    > (string-prefix? “шнурок” “обувь”)     ; Признать префикс строки / суффикс

    #T

    #T

    > (String-Suffix? »Shoelace” Обувь “)

    #f

    > (Строка?” CECI N ‘ est pas une string. “); Признать строки

    #T

    #T

    > (строка? 1)

    #F

    > (SQRT 16); найти квадратный root
    > (SQRT -16)

    0 + 4i

    > (+ 1 2); Добавить номера

    3

    > (- 2 1 ); Вычесть номера

    1

    1

    > (<2 1); Сравнить цифры

    #F

    > (> = 2 1)

    #t

    > (число? “c’est une number”)           ; умбра? 1)

    #t

    > (равно? 6 “полдюжины”)                 ; сравнить что-либо

    #f

    #f

    > (равны? 6 6)

    #T

    > (равны? »Половина десятка” “Половина дюжины”)

    #t

    scrbl")” x-source-pkg=”racket-doc” x-part-tag=”"Conditionals_with_if__and__or__and_cond"”> 2.2.5 Условные выражения с if, and, or, и cond

    Следующий простейший вид выражений — условное if: руководство) объясняет больше об условных выражениях.

    Первое ‹expr› всегда оценивается. Если он производит значение, отличное от #f, то второе выражение ‹expr› равно оценивается по результату всего выражения if, иначе третий ‹expr› оценивается для результата.

    Пример:

    6
    > (если (> 2 3)
    “2 больше 3”
    “2 меньше 3”)

    “2 меньше 3”

    > (Ответить «Привет ракетка»)

    “Привет!”

    > (ответить “λx:(μα. α→α).xx”)

    “а?”

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

    (define (ответ-не-строка s)
      (if (string? s)
     (string-prefix (string-prefix) ? S “HELLO”)
    “HI!”
    “huh?”)
    “huh?”))

    вместо дублирования “а”? ” случае эта функция Лучше написано как

    (определить (Ответить-некруточно)
    (если (если (строки? S)
    (String-Prefix? S »Hello”)
    # f)
          “привет!”
          “а?”))

    , но такие вложенные ЕСЛИ трудно читать. ракетка обеспечивает более читаемые ярлыки через и и или формы:

    Объединение тестов: и и или (далее в этом руководстве) объясняет больше об и и или.

    ( и ‹expr›* )
    ( или ‹expr›* )
    и возвращает короткое замыкание. когда выражение производит #f, в противном случае оно сохраняет идущий. Или образуют аналогичные короткие замыкания, когда встречает истинный результат.

    Примеры:

    > (ответ-нестрока “привет ракетка”)

    “привет!”

    > (ответ-не-строка 17)

    “а?”

    Обратите внимание, что в приведенной выше грамматике формы and и or работать с любым количеством выражений.

    Примеры:

    > (только ответ-восторженное “привет, ракетка!”)

    “привет!”

    > (только ответ-восторженное “привет ракетка”)

    “а?”

    Другой распространенный шаблон вложенных ЕСЛИ включает последовательность Тесты, каждый со своим результатом:

    (определить – больше s)
    (если (префикс строки? Hello »)
    ” HI! “
    Если (string-prefix? s “до свидания”)
    “BYE!”
    (если (string-suffix? s “?”)
    “Я не знаю”
    “да?”))))

    Сокращение для последовательности тестов – форма cond:

    Цепочка тестов: cond (далее в этом руководстве) объясняет больше о cond.

    ( cond {[ ‹expr› ‹expr›* ]}* )

    Форма cond содержит последовательность предложений между квадратами кронштейны. В каждом предложении первое ‹expr› является проверкой выражение. Если он возвращает true, то оставшаяся часть предложения ‹expr› оцениваются, а последнее в предложении обеспечивает ответ для всего условного выражения; остаток от оговорки игнорируются. Если тест ‹expr› выдает #f, тогда остальные ‹expr› предложения игнорируются, и оценка продолжается со следующего пункта.В последнем предложении можно использовать else как синоним тестового выражения #t.

    Используя условие, функция ответа больше может быть больше Четко написано следующим образом:

    > (Ответ-подробнее “Hello Racket”)

    “Привет!”

    > (ответить далее “прощай, жестокий мир”)

    “пока!”

    > (ответить больше “какой ваш любимый цвет?”)

    “Я не знаю”

    > (ответить больше “9083 зеленый лайм0”)

    “а?”

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

    2.2.6 Вызовы функций, снова

    В нашей предыдущей грамматике вызовов функций мы упростили. То фактический синтаксис вызова функции допускает произвольное выражение для функции, а не просто ‹id›:

    Вызовы функций (далее в этом руководстве) объясняет больше о вызовах функций.

    ( ‹expr› ‹expr›* )

    Первым ‹expr› часто является ‹id›, например как добавление строки или +, но это может быть что угодно, что оценивается как функция. Например, это может быть условное Выражение:

    “Mnahmnah”

    “Mnahmnah”

    > (Двухместный 5)

    10

    Синтаксически первое выражение в вызове функции может даже быть числом — , но это приводит к ошибке, так как число не является функция.

    > (1 2 3 4)

    заявка: не процедура;

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

    2.2.7 Анонимные функции с лямбда-выражением

    Программирование в Racket было бы утомительным, если бы вам приходилось называть все свои числа.Вместо записи (+ 1 2) вам нужно будет написать

    Функции: лямбда (далее в этом руководстве) объясняет больше о лямбда.

    Оказывается, называть все ваши функции может быть утомительно, слишком. Например, у вас может быть функция дважды, которая принимает функция и аргумент. Использование дважды удобно, если вы Уже есть имя для функции, такие как SQRT:

    (определить (дважды f v)
    (f (f v)))

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

    > (Дважды громче “Здравствуйте”)

    “Hello !!”

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

    ( lambda ( ‹id›* ) ‹expr›+ )

    Вычисление лямбда-формы само по себе создает функцию:

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

    Другое использование лямбда в результате для функции, которая Генерирует функции:

    > (Дважды (Make-Add-Suffix »!”) “Hello”)

    “Hello !!”

    > (дважды (сделать-добавить-суффикс “?!”) “привет”)

    “привет?!?!!”

    > (дважды (сделать-добавить-суффикс “…”) “hello”)

    “hello….”

    Racket – это язык с лексической областью видимости, что означает, что s2 в функции, возвращаемой make-add-suffix всегда относится к аргументу вызова, создавшего функция. Другими словами, генерируемая лямбда функция «запоминает» правильный s2:

    > (определить громче (сделать-добавить-суффикс “!”))
    > (определить менее уверенный (сделать-добавить-суффикс “?”))
    > (дважды менее уверенно “правда”)

    “правда??”

    > (два раза громче “правда”)

    “правда!!”

    До сих пор мы ссылались на определения формы (define ‹id› ‹expr›) как на «нефункциональное определения.«Эта характеристика вводит в заблуждение, поскольку ‹expr› может быть лямбда-формой, и в этом случае определение эквивалентно использованию определения «функция» форма. Например, следующие два определения громче Equivalent:

    9250

    > Лучший

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

    2.2.8 Локальная привязка с определить, позволить и позволить*

    Пришло время отказаться от еще одного упрощения в нашей грамматике Ракетка. В теле функции определения могут стоять перед выражения тела:

    Внутренние определения (далее в этом руководстве) поясняет больше о локальных (внутренних) определениях.

    (определите ( *) <определение> * +)
    (лямбда ( *) <определение> * +)

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

    Примеры:

    Примеры:

    (определение (Converse S)
    (определить (запуск? S2); локальный для Converse
    (определить Spacts-S2 (String-Append S2 »») ); Местные начнется?
    (Spring-Prefix Spaced-S2))
    (COND
    [(начинается? »Hello”) “Привет!”]
    Начинается? “До свидания”) “пока!”]
    [elit “huh?”]))
    > (Converse “Hello World”)

    “Привет !”

    > (конверсия “helloearth”)

    “а?”

    > (конверс “до свидания, друзья”)

    “пока!”

    > (конверсия “urp”)

    “а?”

    > начинается? ; вне конверсии, т. е…

    начало?: не определено;

     не может ссылаться на идентификатор до его определения

     в модуле: верхний уровень

    Другой способ создания локальных привязок. Ан Преимущество let в том, что его можно использовать в любом выражении. позиция. Кроме того, let связывает сразу много идентификаторов, а не требования отдельного определения для каждого идентификатора.

    Внутренние определения (далее в этом руководстве) объясняет больше о let и let*.

    ( let ( {[ ‹id› ‹expr› ]}* ) ‹expr›+ )

    Каждое обязательное предложение представляет собой ‹id› и ‹expr› в квадратных скобках, а выражения после предложений являются телом let. В В каждом предложении ‹id› привязан к результату ‹expr› для использования в организме.

    формы let доступны только в теле let, поэтому обязательные предложения не могут относиться к каждому разное. Форма let*, напротив, позволяет более поздним предложениям используйте более ранние привязки:

    4.10 Пары и списки

    4.10 Пары и списки

    Пары и списки в Руководстве по ракетке представляют пары и списки.

    Пара объединяет ровно два значения. Первое значение доступ к процедуре car, а второе значение равно доступ с помощью процедуры cdr. Пары не изменяемы (но см. Изменяемые пары и списки).

    Список определяется рекурсивно: это либо константа null, или это пара, вторым значением которой является список.

    Список может использоваться как однозначная последовательность (см. последовательности). Элементы списка служат элементами последовательности. См. также в списке.

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

    См. Чтение пар и списков для информации о чтении пары и списки и печать пар и списков для получения информации о печати пар и списков.

    4.10.1 Конструкторы и селекторы пар

    Возвращает #t, если v является парой, и #f в противном случае.

    Примеры:

    Возвращает #t, если v пустой список, #f иначе.

    Примеры:

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

    примеры:

    примеры:

    > ([[X (случайные 4)]
    [O (случайные 4)])
    (COND
    [(> X O) »X WINS
    [(> o x) “o wins”]
    [Иначе “кошачья игра”]))

    “o Wins”

    ‘(1)

    ‘ (1)

    > (Минусы 1 2)

    ‘(1. 2)

    > (Минусы 1′ ())

    Возвращает первый элемент пары p.

    Примеры:

    Возвращает второй элемент пары p.

    Примеры:

    .

    ‘ (2)

    ‘(2)

    ‘()

    > (CDR ‘(1 2))
    > (CDR’ (1))

    Пустой список.

    Примеры:

    Возвращает #t, если v является списком: либо пустой список, либо пара, вторым элементом которой является список. Эта процедура эффективно снимает постоянное время из-за внутреннего кэширования (так что любые необходимые обходы пар, в принципе, может считаться дополнительными затратами на размещение пар).

    Примеры:

    Возвращает только что выделенный список, содержащий vs как его элементы.

    примеры:

    Примеры:

    8

    > (Список 1 2 3 4)

    ‘(1 2 3 4)

    > (Список (список 1 2) (список 3 4))

    ‘((1 2) (3 4))

    Аналогично списку, но последний аргумент используется как конец списка. результат вместо конечного элемента. Результатом является список, только если последний аргумент – это список.

    Примеры:

    Создает список из n элементов, применяя proc к целые числа от 0 до (sub1 n) по порядку. Если lst — результирующий список, затем (list-ref lst i) — значение, произведенное (proc i).

    Примеры:

    4.10.2 Операции со списками

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

    Примеры:

    Возвращает элемент списка в позиции pos, где первый элемент списка имеет позицию 0. Если список имеет pos или меньше элементов, возникает исключение exn:fail:contract.

    Первый аргумент не обязательно должен быть списком; я должен просто начните с цепочки не менее (add1 pos) пар.

    Эта функция занимает время, пропорциональное поз.

    Примеры:

    Возвращает список после первых поз элементов lst. Если в списке меньше элементов pos, то exn:fail:возбуждено исключение контракта.

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

    Эта функция занимает время, пропорциональное поз.

    Примеры:

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

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

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

    Примеры:

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

    Эта функция занимает время, пропорциональное длине lst.

    Пример:

    4.
    10.3 Итерация списка

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

    примеры:

    примеров:

    > (карта (лямбда (номер)
    (+ 1 номер))
    ‘(1 2 3 4))

    ‘(2 3 4 5)

    > (Карта (лямбда (№1 №2)
    (+ №1 №2))
    ‘ (1 2 3 4)
    ‘ (10 100 1000 10000))

    ‘(11 102 1003 10004)

    Аналогично map в том смысле, что proc применяется к каждый элемент lst, но

    Функция andmap на самом деле ближе к foldl, чем map, так как andmap не составить список.Тем не менее, (andmap f (список x y z)) эквивалентен к (и (f x) (f y) (f z)) так же, как (карта f (список x y z)) эквивалентна (список (f x) (f y) (f z)).

    • результат #f если любое приложение proc выдает #f, и в этом случае proc не применяется к более поздним элементам списков; и

    • результат proc применяется к последним элементам из списков; точнее, применение proc до последних элементов в lsts находится в хвосте позиция относительно вызова andmap.

    Если списки пусты, возвращается #t.

    Примеры:

    Аналогично карте в том смысле, что proc применяется к каждый элемент lst, но

    Чтобы продолжить примечание andmap выше, (ormap f (список x y z)) эквивалентен (или (f x) (f y) (f z)).

    • результат #f если каждое приложение proc производит #f; и

    • результат первого применения proc производя значение, отличное от #f, и в этом случае proc не применяется к более поздним элементам списки; применение proc до последнего элементы списка находятся в хвостовой позиции по отношению к вызов ormap.

    Если списки пусты, возвращается #f.

    Примеры:

    Аналогично карте, но proc вызывается только для ее эффект, а его результат (который может быть любым числом значений) игнорируется.

    Пример:

    > (для каждого (лямбда (ARG)
    (Printf »получил ~ A \ N” Arg)
    23)
    ‘(1 2 3 4))
    Подобно карте, foldl применяет процедуру к элементам один или несколько списков.В то время как map объединяет возвращаемые значения в список, foldl произвольно комбинирует возвращаемые значения что определяется проц.

    Если foldl вызывается с n списками, то proc должен принимать n+1 аргументов. Дополнительный аргумент – это комбинированный возврат значения до сих пор. Процедура первоначально вызывается с первым элемент каждого списка, а последний аргумент — init. В последующие вызовы proc, последним аргументом является возврат значение из предыдущего вызова proc. Вход Списки перебираются слева направо, и результат все приложение foldl является результатом последнего приложения проц.Если списки пусты, результат в этом.

    В отличие от foldr, foldl обрабатывает списки в постоянное пространство (плюс пространство для каждого вызова proc).

    примеры:

    примеры:

    > (Сгиб минусы »() ‘(1 2 3 4))

    ‘ (4 3 2 1)

    > (Foldl + 0 ‘(1 2 3 4))

    10

    10

    > (Foldl (лямбда (результат a b)
    (* Результат (- A b)))
    1
    ‘(1 2 3)
    ‘ (4 5 6))

    -27

    -27

    -27

    Как Foldl, но списки пересекаются справа налево.В отличие от foldl, foldr обрабатывает списки в пространство, пропорциональное длине списка (плюс пространство для каждый вызов proc).

    Примеры:

    4.10.4 Фильтрация списка

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

    Пример:

    Возвращает список, аналогичный lst, но без первого элемента lst равно v с использованием процедуры сравнения proc (который должен принимать два аргумента), с v в качестве первого аргумента и элементом в lst в качестве второго аргумента.Если ни один элемент в lst не равен v (согласно proc), lst возвращается без изменений.

    Примеры:

    Изменено в версии 8.2.0.2 базы пакетов: Гарантируется, что вывод экв.? желать если удаление не происходит.

    примеров:

    примеры:

    8

    > (MEMQ 2 (Список 1 2 3 4 5))

    ‘(1 3 4 5)

    > (REMQ’ (2) (список ‘( 1) ‘(2) ‘(3)))

    ‘((1) (2) (3))

    > (remq “2” (список “1” “2” “3 “))

    ‘(“1” “3”)

    > (remq #\c (список #\a #\b #\c))

    A # \ B)

    Примеры:

    28
    > (REMV 2 (Список 1 2 3 4 5))

    ‘(1 3 4 5)

    > ( remv ‘(2) (list ‘(1) ‘(2) ‘(3)))

    ‘((1) (2) (3))

    > (remv “2” ( list “1” “2” “3”))

    ‘(“1” “3”)

    > (remv #\c (list #\a #\b #\c))

    ‘(#\а #\б)

    90 391 То же, что и remove, но удаляет из списка все экземпляры каждый элемент v-lst.

    Пример:

    Изменено в версии 8.2.0.2 базы пакетов: Гарантируется, что вывод экв.? желать если удаление не происходит.

    Пример:

    Пример:

    Возвращает список, отсортированный по принципу меньше чем? процедура, который принимает два элемента lst и возвращает истинное значение, если первый меньше (т. е. должен быть отсортирован раньше), чем второй.

    Сорт стабильный; если два элемента lst «равны» (т. е. «меньше чем?» не возвращает истинное значение, если задана пара в любой порядок), то элементы сохраняют свой относительный порядок от lst в выходном списке.Чтобы сохранить эту гарантию, используйте сортировать с помощью функций строгого сравнения (например, < или строка

    Из-за того специфического факта, что система счисления IEEE-754 указывает, что +nan.0 не больше и не меньше любого другого числа, сортировка списков, содержащих это значение, может привести к неожиданному результату.

    Аргумент #:key ключ извлечения используется для извлечения ключевое значение для сравнения из каждого элемента списка.То есть полный процедура сравнения по существу

    (лямбда (x y)
     (меньше? (extract-key x) (extract-key y)))

    применяется к двум элементам списка для каждое сравнение, а если кеш-ключи? верно, то Функция извлечения ключа используется ровно один раз для каждого элемента списка. Укажите истинное значение для ключей кеша? при извлечении ключа дорогостоящая операция; например, если file-or-directory-modify-seconds используется для извлечения метки времени для каждого файла в списке, а затем кэш-ключи? должно быть #t, чтобы свести к минимуму вызовы файловой системы, но если extract-key это машина, то кеш-ключи? должно быть #f.Так как другой пример, предоставляющий ключ извлечения как (лямбда (x) (случайно)) и #t для кэш-ключей? эффективно перемешивает список.

    Примеры:

    Примеры:

    > (Сортировать ‘(1 3 4 2) <)

    ‘ (1 2 3 4)

    > (Сортировать ‘(«Aardvark» “Dingo” ” cow” “bear”) string

    ‘(“трубкозуб” “медведь” “корова” “динго”)

    > (sort ‘((“трубкозуб”) dingo”) (“cow”) (“медведь”))
            #:key car string

    ‘((“трубкозуб”) (“медведь”) (“корова” ) (“динго”))

    4.10.5 Поиск по списку
    Находит первый элемент списка, который равен? к v. Если такой элемент существует, хвост lst начиная с этого элемента, возвращается. В противном случае результат #ф.

    Первый аргумент не обязательно должен быть списком; лст должен просто начинать с цепочки пар, пока не будет найден соответствующий элемент. нашел. Если соответствующий элемент не найден, то lst должен быть список (а не циклический список). Результат может быть не списком в случае что элемент найден и возвращенный конец lst является не список.

    Примеры:

    Примеры:

    Примеры:

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

    Пример:

    > (Мемф (лямбда (Arg)
    (> arg 9))
    ‘(7 8 9 10 11))

    ‘(10 11)

    Аналогично memf, но возвращает элемент или #f вместо a хвост lst или #f.

    Пример:

    > (FindF (лямбда (ARG)
    (> Arg 9))
    ‘(7 8 9 10 11))

    10

    Находит первый элемент lst, чей автомобиль равен v в соответствии с равным?. Если такой элемент существует, возвращается пара (т. е. элемент lst). В противном случае результат #f.

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

    Примеры:

    Пример:

    Аналогично assoc, но находит элемент с помощью eq?.

    Пример:

    Аналогично assoc, но находит элемент с использованием предиката процесс; элемент найден, когда proc применяется к car элемента lst возвращает истинное значение.

    Пример:

    4.10.6 Пара Accessor Solidhands

    Пример:

    Пример:

    > (CAAR ‘(((1 2) 3 4))

    1

    3

    > (CADR ‘((1 2) 3 4))

    3

    Пример:

  • 8
  • > (CDAR’ ((7 6 5 4 3 2 1) 8 9 ))

    ‘(6 5 4 3 2 1)

    Пример:

    > (Caaar’ ((((6 5 4 3 2 1) 7) 8 9))
  • 8
  • 6

    6

    Пример:

    7

    Пример:

    > (Caadr ‘(9 (7 6 5 4 3 2 1) 8))

    7

    > (кадар ‘((7 6 5 4 3 2 1) 8 9))

    6

    90 Пример: 90 0386

  • 1

    Пример:

  • > (Chdaar ‘(((6 5 4 3 2 1) 7) 8 9))

    ‘ (5 4 3 2 1)

  • 1

    Пример:

  • > (CDADR ‘(9 (7 6 5 4 3 2 1) 8))

    ‘ (6 5 4 3 2 1)

    > (CDDAR ‘( (7 6 5 4 3 2 1) 8 9))

    ‘(5 4 3 2 1)

    2 1) 6) 7) 8 9))

    5

    6

  • 1

    Пример:

  • 6

    > (Кадар ((7 (5 4 3 2 1) 6) 8 9))

    5

    Пример:

    6

    > (caadd R ‘(9 8 (6 5 4 3 2 1) 7))

    6

    Пример:

    6
    > (Cadaar’ ((((6 5 4 3 2 1) 7 ) 8 9))

    5

    5

    Пример:

    > (Cadadr ‘(9 (7 6 5 4 3 2 1) 8))

    6

    Пример

    Пример:

    5

    > (Caddar ‘((7 6 5 4 3 2 1) 8 9))

    5

    . CDAAAR ‘(((((5 4 3 2 1) 6) 7) 8 9))

    ‘ (4 3 2 1)

    Пример:

    6
    > (CDAADR ‘( 9 ((6 5 4 3 2 1) 7) 8))

    ‘(5 4 3 2 1)

    Пример:

    9082 4 3 2 1) 6) 8 9))

    ‘(4 3 2 1)

    Пример:

    > (CDaddr’ (9 8 (6 5 4 3 2 1) 7))

    ‘(5 4 3 2 1)

    Пример:

    2 Пример:

    > (CDDAAR ‘((((6 5 4 3 2 1) 7) 8 9))

    ‘ (4 3 2 1)

    Пример:

    Пример:

    > (CDDADR ‘(9 (7 6 5 4 3 2 1) 8))

    ‘ (5 4 3 2 1)

    > (cdddar ‘((7 6 5 4 3 2 1) 8 9))

    ‘(4 3 2 1)

    9,63833 90,10.7 Дополнительные функции списка и синонимы

    Пустой список.

    Примеры:

    Примеры:

    Примеры:

    То же, что и (car lst), но только для списков (которые не пусты).

    Пример:

    > (first ‘(1 2 3 4 5 6 7 8 9 10))

    1

    не пусты).

    Пример:

    > (Отдых ‘(1 2 3 4 5 5 6 7 8 9 10))

    ‘ (2 3 4 5 6 7 8 9 10)

    возвращает второй элемент списка.

    Пример:

    1 список третьих элементов.

    Пример:

    > (second ‘(1 2 3 4 5 6 7 8 9 10))

    2

    1 список четвертых элементов 9.

    Пример:

    Пример:

    > (третий ‘(1 2 3 4 5 6 7 8 9 10))

    3

    4

    > (Четвертый ‘(1 2 3 4 5 5 6 7 8 9 10))

    4

    Возвращает пятый элемент списка.

    Пример:

    Пример:

    5

    > (Пятый ‘(1 2 3 4 5 5 6 7 8 9 10))

    5

    Возвращает шестой элемент списка.

    Пример:

    Пример:

    6

    > (Шестые ‘(1 2 3 4 5 5 6 7 8 9 10))

    6

    возвращает седьмой элемент списка.

    Пример:

    Пример:

    > (Седьмое ‘(1 2 3 4 5 5 6 7 8 9 10))

    7

    Возвращает восьмой элемент списка.

    Пример:

    Пример:

    8

    > (восьмой ‘(1 2 3 4 5 5 6 7 8 9 10))

    8

    возвращает девятый элемент списка.

    Пример:

    .

    9

    > (Девятый »(1 2 3 4 5 5 6 7 8 9 10))

    9

    Возвращает десятый элемент списка.

    Пример:

    .

    10

    > (десятый ‘(1 2 3 4 5 5 6 7 8 9 10))

    10

    Возвращает последний элемент списка.

    Эта функция занимает время, пропорциональное длине lst.

    Пример:

    Пример:

    10

    > (Last ‘(1 2 3 4 5 5 6 7 8 9 10))

    10

    возвращает последнюю пару (возможно, неправильный) списка.

    Эта функция требует времени, пропорционального «длине» p.

    Пример:

    Возвращает вновь созданный список длины k, содержащий v во всех положениях.

    Пример. указанный индекс.Элемент по указанному индексу (updater (list-ref lst pos)).

    Эта функция занимает время, пропорциональное поз.

    Добавлено в версии 6.3 базы пакетов.

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

    Эта функция занимает время, пропорциональное поз.

    Пример.3 пакета базы.

    Аналогично элементу, но возвращает индекс первого найденного элемента вместо хвоста списка.

    Пример:

    Добавлено в версии 6.7.0.3 базы пакетов.

    Аналогично index-of, но с поиском предикатов мемф.

    Пример:

    Добавлено в версии 6.7.0.3 базы пакетов.

    Аналогично index-of, но возвращает список всех индексов где элемент встречается в списке, а не только первый.

    Пример:

    Добавлено в версии 6.7.0.3 базы пакетов.

    Пример:

    Добавлено в версии 6.7.0.3 базы пакетов.

    Возвращает новый список, элементы которого являются первыми элементами pos из лст. Если в lst меньше элементов pos, возникает исключение exn:fail:contract.

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

    Эта функция занимает время, пропорциональное поз.

    Примеры:

    Примеры:

    > (Возьмите ‘(1 2 3 4 5) 2)

    ‘ (1 2)

    > (Возьмите ‘не списку 0)

    ‘()

    Возвращает тот же результат, что и

    (значения (взять первую позицию) (отбросить первую позицию))

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

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

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

    Примеры:

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

    Примеры:

    Возвращает тот же результат, что и

    (values ​​(takef lst pred) (dropf lst pred))

    , за исключением того, что может быть быстрее.

    Возвращает конец pos-длины списка. Если лст имеет меньше, чем pos элементов, то exn:fail:возбуждено исключение контракта.

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

    Эта функция занимает время, пропорциональное длине lst.

    Примеры:

    Возвращает новый список, элементы которого являются префиксом lst, отбрасывая хвост длины pos. Если в lst меньше pos, то возникает исключение exn:fail:contract.

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

    Эта функция занимает время, пропорциональное длине lst.

    Примеры:

    Возвращает тот же результат, что и

    (значения (выпадение справа слева поз.) (взять справа слева позиция))

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

    Примеры:

    Истинно, если l является префиксом r.

    Добавлено в версии 6.3 пакета базы.

    Возвращает самый длинный общий префикс l и r.

    Добавлено в версии 6.3 базы пакетов.

    Возвращает хвосты l и r с общим префикс удален.

    Добавлено в версии 6.3 базы пакетов.

    Возвращает самый длинный общий префикс вместе с хвостами l и r с удаленным общим префиксом.

    Добавлено в версии 6.3 базы пакетов.

    (надстройка между LST
    против
    [ #: Перед первым ранее первым #: Долготся до последнего000000 #: Последнее послеведочное #: Splice? Splice?])0 Список?
      lst : список?
      v : any/c
      before-first : list? = ‘()
      до последнего : any/c = v
      после последнего : list? = ‘()
      склеить? : any/c = #f

    Возвращает список с теми же элементами, что и lst, но с v между каждой парой элементов в lst; последняя пара элементов будет иметь предпоследний между ними, а не v (но перед последним значением по умолчанию v).

    Если сращивать? верно, то v и предпоследний должны быть списками, и элементы списка объединяются в результат. В Кроме того, при сращивании? верно, перед первым и after-last вставляются перед первым элементом и после последний элемент соответственно.

    Примеры:

    .

  • 8
  • 28
    > (add-между ‘(x y z)’ и)

    ‘(x and y and z)

    > (add – между’ (x) ‘и)

    ‘(x)

    > (добавить между ‘(“a” “b” “c” “d”) “,” #:перед последним “и”)

    ‘(“а” “”, “б” “,” “в” “и” “г”)

    > (добавить-между ‘(x y z) ‘(- ) #: До последнего ‘(- -)
    #: До сначала’ (начало) #: Последнее «(End LF)
    #: Splice? #T)

    ‘(начало x – y – – z конец LF)

    Примеры:

    > (append* ‘(a) ‘(b) ‘((c) )))

    ‘(abcd)

    > (cdr (append* (map (лямбда (x) (список “, ” x)) 9083 0
    ‘( “Альфа”, “Бета”, “Гамма”))))

    ‘ ( “Альфа” ” ” “Бета””,” “Гамма”)

    Преобразует произвольную структуру пар S-выражений в список.Более именно, v рассматривается как бинарное дерево, в котором пары внутренние узлы, и результирующий список содержит все ненулевые листья дерева в том же порядке, что и неупорядоченные обход.

    Примеры:

    8 > сгладить
    > (сплющить ‘((a) b (c (d) . e) ()))

    ‘(abcde)

    '(a)

    Возвращает первый повторяющийся элемент в списке.Точнее, это возвращает первый x такой, что был предыдущий y где (такое же? (извлечение ключа x) (извлечение ключа y)).

    Если дубликат не найден, то результат ошибки определяет результат:

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

    • В противном случае в качестве результата возвращается результат отказа.

    То же самое? аргумент должен быть предикатом эквивалентности, таким как равный? или экв? или словарь.Процедуры equal?, eqv? и eq? автоматически используйте словарь для скорости.

    Примеры:

    Добавлено в версии 6.3 базы пакетов.
    Изменено в версии 6.11.0.2: Добавлен необязательный аргумент #:default.

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

    Ключ извлечения аргумента #:key используется для извлечения значение ключа из каждого элемента списка, поэтому два элемента считаются равными, если (такое же? (извлечение ключа x) (извлечение ключа y)) истинно.

    Примеры:

    Like (map proc lst ...), за исключением того, что если proc возвращает #false, этот элемент исключается из результирующего списка. Другими словами, filter-map эквивалентен (filter (lambda (x) x) (map proc lst...)), но более эффективный, потому что filter-map избегает построение промежуточного списка.

    Пример:

    Пример:

    Аналогично фильтру, за исключением того, что возвращаются два значения: элементы, для которых pred возвращает истинное значение, а элементы для который возвращает #f.

    Результат аналогичен

    (values ​​(filter pred lst) (filter (negate pred) lst))

    , но pred применяется к каждому элементу списка только один раз.

    Пример:

    Результирующий список содержит числа, начинающиеся с начала и чьи последовательные элементы вычисляются путем добавления шага к их предшественник, пока не будет достигнут конец (исключен). Если нет запуска указывается точка, используется 0. Если нет аргумента шага при условии, 1 используется.

    Как и в диапазоне, приложение диапазона может обеспечить лучшее производительность, когда она появляется непосредственно в предложении for.

    примеры:

    примеры:

    > (Диапазон 10)

    '(0 1 2 3 4 5 6 7 8 9)

    > (Диапазон 10 20)

    ' ( 10 11 12 13 14 15 16 17 18 18 19)

    > (Диапазон 20 40 2)

    '(20 22 24 26 28 30 32 34 36 38)

    > (Диапазон 20 10 -1)

    '(20 19 18 17 16 15 14 13 12 11)

    > (диапазон 10 15 1.5)

    '(10 11,5 13,0 14,5)

    Изменено в версии 6.7.0.4 базы пакетов: настроено для взаимодействия с for в том же так, как это делает в диапазоне.

    Результирующий список содержит номера, начинающиеся с начала и чьи последовательные элементы вычисляются путем добавления шага к их предшественник, пока не будет достигнут конец (включительно). Если аргумент шага не указан, используется 1.

    Как и in-inclusive-range, приложение inclusive-range может обеспечить лучшее производительность, когда она появляется непосредственно в предложении for.

    Примеры:

    Добавлено в версии 8.0.0.13 базы пакетов.

    Пример:

    Аналогично фильтру, но предикат предиката имеет другое значение. наоборот: результатом является список всех элементов, для которых пред возвращает #f.

    Пример:

    Возвращает список со всеми элементами из списка, перемешанными случайным образом.

    Примеры:

    Примеры:

    2 5 5 3 (6 3 4'91)

    > (Shuffle '(1 2 3 4 5 5 6))

    ' (5 4 1 3 6 2)

    > (Shuffle '(1 2 3 4 5 6))

    '(3 1 4 2 6 5)

    > (перемешать '(1 2 3 4 5 6))
    Вернуть список всех комбинаций элементов в списке ввода (иначе набор мощности lst).Если задан размер, ограничьте результаты комбинациями элементов размера.

    Примеры:

    3 90 возвращает последовательность всех s комбинации элементов во входном списке, или все комбинации размера длины, если указан размер.Строит комбинации по одной, а не все сразу.

    Примеры:

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

    Примеры:

    Возвращает последовательность всех перестановок входного списка. это эквивалентно (в списке (перестановки l)), но намного быстрее, так как он строит перестановки одну за другой на каждой итерации.Выдает ошибку, если входной список содержит более 256 элементов. Возвращает первый элемент в списке lst, который минимизирует результат проц. Сигнализирует об ошибке в пустом списке. См. также мин.

    Примеры:

    > (комбинации '(1 2 3))

    '(() (1) (2) (1 2) (3) (1 3) (2 3) (1 2 3))

    > (комбинации '(1 2 3) 2)

    '((1 2) (1 3) (2 3))

    908 908 1 банан) (1 апельсин)))
    > (argmin car ‘((3 груши) (1 банан) (2 яблока)))

    ‘(1 банан)

    ‘(1 банан)

    Возвращает первый элемент списка lst, максимизирующий результат проц.Сигнализирует об ошибке в пустом списке. См. также макс.

    Примеры:

    9’max22
    > (argmax car ‘((3 груши) (1 банан) (2 яблока)))

    ‘(3 груши)

    3 груши) (3 апельсина)))

    ‘(3 груши)

    Группирует данный список в классы эквивалентности, при этом эквивалентность определяется же?. Внутри каждого класса эквивалентности сохраняет порядок исходного списка.Сами классы эквивалентности в порядке первого появления во входных данных.

    Пример:

    > (группировать по (лямбда (x) (по модулю x 3)) ‘(1 2 1 2 54 2 5 43 7 2 643 1 2 0))

    ((( 1 1 43 7 643 1) (2 2 2 5 2 2) (54 0))

    Добавлено в версии 6.3 базы пакетов.

    Вычисляет n-арное декартово произведение заданных списков.

    Примеры:

    > (декартово произведение ‘(1 2 3) ‘(a b c))

    ‘((1 a) (1 b) (1 c) (2 a) (2b) (2c) (3a) (3b) (3c))

    > (декартово произведение ‘(4 5 6) ‘(d e f) ‘(#t #f) )

    (4 e #t)

    8

    8

    (5 е #t)

    (5 f #t)

    8

    (6 e #f)

    8

    828

    ‘((4 д #t)

    (4 d #f)

    (4 e #F)

    (4 f #t)

    (4 f #f)

    (5 D #T)

    (5 D #F )

    (5 e #f)

    (5 f #f)

      (6 д #т)

    9003 2 (6 D #F)

    (6 е #t)

    (6 F #T)

    6 f #f))

    Добавлено в версии 6.3 пакета базы.

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

    Добавлено в версии 6.3 базы пакетов.

    То же, что и remf, но удаляет все элементы, для которых предварительно производит истинное значение.

    Добавлено в версии 6.3 базы пакетов.

    4.10.8 Неизменяемые циклические данные
    Возвращает значение, подобное v, с заполнителями, созданными make-placeholder заменен значениями, которые они содержат, и с заполнителями, созданными make-hash-placeholder с неизменяемая хеш-таблица.Никакая часть v не мутирована; вместо этого части из v копируются по мере необходимости для построения результирующего графа, где для любого заданного значения создается не более одной копии.

    Поскольку скопированные значения могут быть неизменяемыми, а копия также неизменяемый, make-reader-graph может создавать циклы, включающие только неизменяемые пары, векторы, блоки и хеш-таблицы.

    Добавить комментарий

    Ваш адрес email не будет опубликован.