значения coffeescript и enum - PullRequest
       15

значения coffeescript и enum

9 голосов
/ 21 февраля 2012

Я поиграл с концепцией перечислений / констант в coffeescript (http://coffeescript.org/) и придумал следующий код, который выглядит нормально. Как я могу улучшить это, чтобы быть еще лучше для чего-то, где подходит перечисление? Поиск в Google по этому поводу еще не показал удовлетворения.

class SomeService

  @SomeEnumValue : 400
  @SomeOtherValue : 402

  someFunc: ->
    SomeService.SomeEnumValue 

ok = new SomeService()
alert ok.someFunc()

if (ok.someFunc() == SomeService.SomeEnumValue) then alert ' some enum value'

Ответы [ 5 ]

19 голосов
/ 22 февраля 2012

Вся концепция enum просто бесполезна в динамических языках, как кортеж, типизированный список, карта и множество других вещей, а Javascript (Coffeescript) является динамическим.При работе с динамическим языком вам просто нужно забыть о проверке типов и использовать существующие более общие конструкции для решения вашей проблемы.Используйте массивы вместо списков и кортежей, используйте объекты вместо карт и перечислений и просто доверяйте типу значений, передаваемых функции, но тщательно тестируйте свой код.К лучшему или к худшему (для худшего ИМО), вот как здесь делается работа.

В вашем случае я бы рекомендовал просто хранить ваши значения в одноэлементном объекте, например:

HTTPStatusCodes = 
  ok : 200
  badRequest : 400
  unauthorized : 401

и доступ к нему так:

class SomeService
  okCode: ->
    HTTPStatusCodes.ok
  failureCodes: ->
    code for key, code of HTTPStatusCodes when code >= 400
5 голосов
/ 10 мая 2013

Я знаю, что я опаздываю на вечеринку, но для потомков я предлагаю «кофейное» решение (в духе меньшего набора текста):

[ a, b, c ] = [1..3]
4 голосов
/ 08 августа 2012

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

Цитируя Википедию: «Переменной, которая была объявлена ​​как имеющая перечисляемый тип, может быть назначен любой из перечислителей в качестве значения». И только эти перечислители возможны в качестве значений.

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

Я создал пример, который в основном функциональный и использует анонимный обратный вызов функционирует как средство присваивания - в основном подставляя оператор присваивания "=" для Coffeescripts оператор функции "->". Это делает самый синтаксически плотный код в моей книге. Однако более классовый подход, безусловно, возможен.

#define enumeration
httpcodes = Enum 
    ok: 200
    badRequest: 400
    unauthorized: 401
    server_error: 500

#set enum variables with some default state
chrome = httpcodes -> @server_error 
firefox = httpcodes -> @server_error
safari = httpcodes -> @server_error

console.log "httpcodes.ok:" + httpcodes.ok

#change enum value
chrome -> @ok
firefox -> @badRequest
safari -> @unauthorized

console.log "chrome:" + chrome ->
console.log "firefox:" + firefox ->
console.log "safari:" + safari ->

console.log "(chrome ->) == httpcodes.ok:" + ((chrome ->) == httpcodes.ok)

#set an invalid value
try
    safari -> 999
catch err
    console.log err 
    console.log "safari:" + safari ->

А вот код для создания Enum (вам нужно поместить его поверх кода если вы хотите запустить его. Просто хотел показать код использования перед кодом реализации

Enum = (enumeration)->
    check = (value)->
        newval = null
        for key, val of enumeration
            if val == value
                newval = value
                break
        if !newval
            throw "Invalid Enum Value: #{value}"

     result = (init)->
         state = init.call(enumeration)
         check state
         (callback)->
              value = callback.call(enumeration)
              if value == null or value == undefined
                  return state
              else
                  check value
                  state = value

      for key, value of enumeration
          result[key] = value 

      result

Очевидно, было бы намного приятнее, если бы Coffeescript имел синтаксические макросы. Таким образом, мы могли бы написать

Enum httpcodes
    ok: 200
    badrequest: 400

и

chrome = httpcodes 'ok
#or
chrome := 'ok
2 голосов
/ 08 сентября 2015
Colors = Object.freeze({
  RED: 'red'
  GREEN: 'green'
  BLUE: 'blue'
})
console.log Colors.RED
# red

Значения являются константами (их нельзя изменить):

Colors.RED = 'black'
console.log Colors.RED
# red
1 голос
/ 20 октября 2015

Я начал день с размышлений о enums в coffeescript и закончил его решением Я опубликовал на github (доступно в npm, bower, meteor тоже) . Я пытался разработать java-подобные перечисления, но еще более гибкие, учитывая сочетание наследования прототипа и классического наследования, на которое опирается coffeescript.

Вот как это будет соответствовать вашему коду:

class SomeService
  someFunc: -> SomeService.SomeEnumValue
  #A cool hack, but it must be the last class statement. 
  #Your class will now inherit this enumeration's properties. 
  #If you find this too hacky, you can always have a public static 
  #states class property instead.
  @__proto__:new Enumeration('SomeService',{
          SomeEnumValue :400
          SomeOtherValue:402
      })

ok = new SomeService()

alert ok.someFunc().id() #shows 400

if (ok.someFunc() is SomeService.SomeEnumValue) then alert ' some enum value'

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

class SomeService
  someFunc: -> SomeService.SomeEnumValue
  #A cool hack, but it must be the last class statement. 
  #Your class will now inherit this enumeration's properties. 
  #If you find this too hacky, you can always have a public static 
  #states class property instead.
  @__proto__:new Enumeration('SomeService',
                SomeEnumValue : { _id:400, text: ' some enum value' }
                SomeOtherValue: { _id:402, text: null } 
        , tell:->if @text? then alert @text)

ok = new SomeService()

alert ok.someFunc().id() #shows 400

ok.someFunc().tell()

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

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