2013-07-26 2 views
2

Исходя из Scala, отсутствие затенения в CoffeeScript кажется очень странным. Я написал демо.Почему недостаток затенения в CoffeeScript считается приемлемым

object ZekeDemo extends App { 

    val filterAll = (arr: Seq[String]) => { 
    val saved = ArrayBuffer[String]() 
    val removed = ArrayBuffer[String]() 

    val filterDo = (arr: Seq[String]) => { 
     val saved = for {item <- arr if item != "do"} yield item 
     val removed = for {item <- arr if item == "do"} yield item 
     (saved, removed) 
    } 

    val filterSo = (arr: Seq[String]) => { 
     val saved = for {item <- arr if item != "so"} yield item 
     val removed = for {item <- arr if item == "so"} yield item 
     (saved, removed) 
    } 

    val addRemoved = (item: String) => removedBuff += item 
    val addSaved = (item: String) => savedBuff += item 

    for {item <- filterDo(arr)._1} { addSaved(item)} 
    for {item <- filterDo(arr)._2} { addRemoved(item)} 

    for {item <- filterSo(arr)._1} { addSaved(item)} 
    for {item <- filterSo(arr)._2} { addRemoved(item)} 

    (saved, removed) 
    } 

    val song = Seq("do", "re", "mi", "fa", "so") 

    val s = filterAll(song)._1 
    val r = filterAll(song)._2 

    println("saved: %s, removed: %s".format(s.mkString(","), r.mkString(","))) 

} 

Теперь вот та же программа в CoffeeScript:

filterAll = (arr) -> 

    saved = [] 
    removed = [] 

    filterDo = (arr) -> 
    saved = -> 
     item for item in arr when item != "do" 
    removed = -> 
     item for item in arr when item == "do" 
    {"saved":saved(), "removed":removed()} 

    filterSo = (arr) -> 
    saved = -> 
     item for item in arr when item != "so" 
    removed = -> 
     item for item in arr when item == "so" 
    {"saved":saved(), "removed":removed()} 

    addRemoved = (item) -> 
    saved[saved.length] = item 

    addSaved = (item) -> 
    removed[removed.length] = item 

    addRemoved item for item in filterDo(arr)["removed"] 
    addSaved item for item in filterDo(arr)["saved"] 

    addRemoved item for item in filterSo(arr)["removed"] 
    addSaved item for item in filterSo(arr)["saved"] 

    {"saved":saved, "removed":removed} 

song = ["do", "re", "mi", "fa", "so"] 

s = filterAll(song)["saved"] 
r = filterAll(song)["removed"] 

alert("saved: " + s + ", removed: " + r) 

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

Это кажется мне очень странным. Большую часть красотки функциональных языков не нужно знать о внешних областях. Если я напишу свою функцию «filterDo» в другом контексте (class | function | file), я считаю, что должен уметь ее переносить в любой другой контекст, где это допустимый синтаксис, и не нужно беспокоиться о том, наступает ли он на значения из внешний охват.

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

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

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

+0

Я подозреваю, что проблема в том, что вы ошибаетесь в отношении того, какой объем (я не знаю coffeescript, поэтому не знаю). Например, в python все переменные внутри функции находятся в одной области, поэтому вы не можете дублировать имена внутри функции. – Marcin

+1

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

+1

Это больше похоже на напыщенный вопрос, чем на вопрос ... Во всяком случае, вместо этого перейдите к [ClojureScript] (http://himera.herokuapp.com/index.html) - проблема решена! : D – DaoWen

ответ

1

Я думаю, что на практике вы вряд ли столкнетесь с этим при написании небольших определений и классов и т. Д. И избегаете чрезмерных/чрезмерно общих глобальных переменных (т. Е. Когда вы пишете «хороший код»). Ваш пример кажется особенно надуманным. Вот простое решение для filterAll() функции:

filterAll = (arr) -> 
    saved: item for item in arr when item not in ['do', 'so'] 
    removed: item for item in arr when item in ['do', 'so'] 

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

Кроме того, по умолчанию, если вы не указали иначе, ваши скомпилированные файлы CoffeeScript будут автоматически завернуты в блокировки. Поэтому, даже если вы напишите «плохой код» и поместите верхний уровень с кучей общих имен var, вы никогда не будете случайно топать на «глобальных» vars других файлов (не глобально больше, учитывая закрытие, глобальное для файла).

Я думаю, что предложение где-то на Interwebz в виде := оператора явно обозначать назначение в вар во внешней сфере с тем же именем является звуком предложения (и компилятором по умолчанию всегда буду переобъявить var в области видимости).Однако на данный момент это будет новая крупная версия для CoffeeScript, потому что она сломает тонн кода, написанного людьми, знающими язык и фактически использующими то, что вы видите как проблему. ;)

Надеюсь, это поможет. Неожиданным сюрпризом является то, что приложение Demo Scala имеет мое имя. Я люблю Scala и CoffeeScript!

Смежные вопросы