Статьи

Обработка списка в CoffeeScript

Итак, вы кодируете свой CoffeeScript и у вас есть список, с которым вам нужно иметь дело. В JavaScript есть широкий набор (предназначенных для каламбура) методов, которые вы можете использовать для облегчения своей жизни, но CoffeeScript дает вам преимущество в виде краткого и согласованного синтаксиса. Вместо того, чтобы смешивать циклы, forEach() jQuery forEach() и вызывать (превосходную) библиотеку Underscore, вы можете сделать все кратко и читабельно.

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

Ломтик и кости

Допустим, вы создаете гибридную гоночную / шоппинг-игру Cario Mart. Во время игры вы позволяете людям покупать грибы и ракушки для использования в своих машинах (не спрашивайте). Чтобы сделать игру более увлекательной и конкурентоспособной, вы хотите сделать вещи дешевле для игроков на 6-м, 7-м и 8-м местах (проигравших игроков). Вот один из способов сделать это в CoffeeScript, если предположить, что список игроков упорядочен в соответствии с тем, в каком месте они находятся:

 if player == players[5] or player == players[6] or player == players[7] blueShroom.cheaperFor(player) 

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

 if player in [players[5], players[6], players[7]] blueShroom.cheaperFor(player) 

Но вот реализация, которая в полной мере использует синтаксис CoffeeScript:

 if player in players[5..7] blueShroom.cheaperFor(player) 

Теперь, если вы хотите что-то изменить в этом отношении (какой игрок вы сравниваете, какой список игроков вы используете, какие места вы хотите затронуть), вам нужно всего лишь изменить одну вещь в одном месте. Одна последняя оптимизация — скажем, ваша игра внезапно расширяется до девяти человек вместо восьми. В настоящее время выигрывают игроки в местах 6-8, оставляя страдать бедного игрока с 9-м местом. Давайте исправим это, прежде чем двигаться дальше, сделав так, чтобы кто-то на 6-м месте и с меньшими преимуществами:

 if player in players[5..] blueShroom.cheaperFor(player) 

Список Пониманий

Итак, вы на седьмом месте и только что купили синий гриб. Теперь вы хотите использовать это. В этом случае синий гриб попадает в чужой бензобак и случайно загорает их автомобиль. Ой! Это отбросит их на несколько секунд. Теперь то, что вам нужно из вашего кода, это способ атаковать всех, кроме вас самих.

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

 players.forEach (target) -> blueShroom.poison(target) unless target is buyer 

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

 for target in players blueShroom.poison target unless target is buyer 

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

 blueShroom.poison target for target in players unless target is buyer 

Вау, это самый англоязычный код! Если вы не уверены, что происходит, вернитесь к первой версии, которая выглядела как код. Вот тот, который использует еще несколько ключевых слов CoffeeScript, которые немного лучше на английском языке:

 blueShroom.poison target for target in players when target isnt buyer 

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

Как это ни круто, есть две ловушки, чтобы перечислить понимание:

  1. Список пониманий возвращает список (в данном случае список отравленных целей). Это замечательно, если вы хотите «сложить» списки, но если вы сложите больше двух, это может быстро запутаться. Это особенно верно, если вы опускаете необязательные скобки и скобки.
  2. Поскольку это может выглядеть так же, как английский, вы можете иногда написать правильное английское предложение и удивиться, что оно не компилируется. Столько же усилий, сколько CoffeeScript делает, чтобы сделать ваш код похожим на английский, если вы допустите ошибку, думая, что это одно и то же, вы быстро вернетесь к реальности.

Splats

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

 tellPlayers = (message) -> player.socket.emit(message) for player in players 

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

Это прекрасно работает, если сообщение простое, как gameEnded . Но что, если после окончания игры мы хотим отправить имя победителя всем? Мы могли бы написать это так:

 tellPlayers = (message, argument) -> player.socket.emit(message, argument) for player in players 

Теперь это работает, но что, если мы отправим сообщение «восклицательный знак» всякий раз, когда кто-то будет поражен оружием (например, синим шрумом)? Здесь мы хотим знать оружие, удар игрока и игрока, который послал атаку. Это три аргумента! Способ обойти это через знаки.

 tellPlayers = (message, arguments...) -> player.socket.emit(message, arguments...) for player in players 

Когда вы ставите три точки после этого, это означает, что аргумент на самом деле является списком аргументов. Может быть 1, 3, 0 или любое количество аргументов. Это как если бы вы бросили список, и все отдельные аргументы разлетелись по стене.

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

 tellPlayers('listOfPlayers', players...) 

Это вызывает нашу предыдущую функцию. На стороне клиента у нас есть следующее:

 socket.on 'listOfPlayers', (first, second, third, rest....) -> celebrate(first) celebrate(second) celebrate(third) hands.clap() for hands in rest 

Весь список игроков передается через сокет с помощью знака «сплат», затем, когда он получен, он выбирает первые три для празднования, а rest... знак «Сплат» поглощает все остальное.

Важно, чтобы при вызове tellPlayers вы использовали tellPlayers для players . В противном случае он будет использовать весь список в качестве первого аргумента, что приведет к тому, что клиент будет отмечать всех восьми игроков, затем будет отмечать два null значения, и никто не будет хлопать в ладоши. Мы не можем этого иметь!

Твой выбор

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

Кроме того, SitePoint только что выпустил новейшую серию Jump Start: Jump Start: CoffeeScript . Узнайте, как сделать потрясающий HTML5 2D-платформер, наполненный ниндзя, используя CoffeeScript… и все в один уик-энд!

Наконец, в разделе «Learnable» Пол Аннесли проведет вас через короткое видео JumpCast на CoffeeScript. Пьянящий напиток!