Почему Clojure имеет “ключевые слова” в дополнение к “символам”?

Один вариант с rleid из data.table. После преобразования в data.table (setDT(df)) сгруппируйте по идентификатору длины серии V3, replace последний элемент V2 с first V1 и назначьте (:= ) это к 'V2'

library(data.table)
setDT(df)[, V2 := replace(V2, .N, first(V1)), rleid(V3)]
df
#   V1 V2 V3
#1:  1  2  1
#2:  2  3  1
#3:  3  4  1
#4:  4  1  1
#5:  5  6  2
#6:  6  7  2
#7:  7  5  2
#8:  9 10  3
#9: 10  9  3

данных

df <- structure(list(V1 = c(1L, 2L, 3L, 4L, 5L, 6L, 7L, 9L, 10L), V2 = c(2L, 
 3L, 4L, 5L, 6L, 7L, 8L, 10L, 11L), V3 = c(1L, 1L, 1L, 1L, 2L, 
   2L, 2L, 3L, 3L)), class = "data.frame", row.names = c(NA, -9L
  ))
125
задан Martin Josefsson 3 March 2014 в 01:57
поделиться

5 ответов

Вот документация Clojure для ключевых слов и символов.

Ключевые слова - это символьные идентификаторы, которые оцениваются сами по себе. Они обеспечивают очень быстрые проверки на равенство ...

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

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

Самый простой способ увидеть разницу - прочитать Keyword.java и Symbol.java в исходном коде Clojure. Есть несколько очевидных различий в реализации. Например, у символа в Clojure могут быть метаданные, а у ключевого слова - нет.

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

user> :foo
:foo
user> ::foo
:user/foo

Common Lisp имеет ключевые слова, как и Ruby и другие языки. Конечно, на этих языках они немного отличаются. Некоторые различия между ключевыми словами Common Lisp и ключевыми словами Clojure:

  1. Ключевые слова в Clojure не являются символами.

     user> (symbol?: Foo) Например, символ в Clojure может иметь метаданные, а ключевое слово - нет. 

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

    user> :foo
    :foo
    user> ::foo
    :user/foo
    

    Common Lisp имеет ключевые слова, как и Ruby и другие языки. Конечно, на этих языках они немного отличаются. Некоторые различия между ключевыми словами Common Lisp и ключевыми словами Clojure:

    1. Ключевые слова в Clojure не являются символами.

       user> (symbol?: Foo) Например, символ в Clojure может иметь метаданные, а ключевое слово - нет. 

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

      user> :foo
      :foo
      user> ::foo
      :user/foo
      

      Common Lisp имеет ключевые слова, как и Ruby и другие языки. Конечно, на этих языках они немного отличаются. Некоторые различия между ключевыми словами Common Lisp и ключевыми словами Clojure:

      1. Ключевые слова в Clojure не являются символами.

         user> (symbol?: Foo)
        ложный
        
      2. Ключевые слова не принадлежат ни к какому пространству имен, если вы специально не указали их:

         пользователь> (пространство имен: foo)
        ноль
        пользователь> (пространство имен :: foo)
        "пользователь"
        

      (Спасибо Райнеру Йосвигу за то, что он дал мне идеи, на которые можно смотреть.)

135
ответ дан 24 November 2019 в 01:01
поделиться

Ключевые слова глобальны , символы не .

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

const foo = Symbol.for(":foo") // this will create a keyword
const foo2 = Symbol.for(":foo") // this will return the same keyword
const foo3 = Symbol(":foo") // this will create a new symbol
foo === foo2 // true
foo2 === foo3 // false

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

(println :foo) ; Clojure
System.out.println(RT.keyword(null, "foo")) // Java
console.log(System.for(":foo")) // JavaScript

Они являются всеми одинаковыми.

<час>

имена Аргумента функции локальны. т.е. не ключевые слова.

(def foo (fn [x] (println x))) ; x is a symbol
(def bar (fn [x] (println x))) ; not the same x (different symbol)
0
ответ дан 24 November 2019 в 01:01
поделиться

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

6
ответ дан 24 November 2019 в 01:01
поделиться

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

(:user-id (get-users-map))

такой же, как

((get-users-map) :user-id)

, это делает вещи немного более гибкими

4
ответ дан 24 November 2019 в 01:01
поделиться

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

Единственное исключение - назначение.
float a = 10.0;
float b = 10.0;
then a == b

В противном случае вам всегда придется писать некоторую функцию, например bool IsClose (float a, float b, float error), чтобы вы могли проверить, находятся ли два числа в пределах «ошибки» друг от друга.
Не забудьте также проверить знаки / использовать фабрики - вы можете иметь -1.224647e-16

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

    Помните: в Common Lisp символы принадлежат пакету. Это можно записать как:

    • foo, когда символ доступен в текущем пакете
    • foo: bar, когда символ FOO экспортируется из пакета BAR
    • foo :: bar, когда символ FOO - в пакете BAR

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

    Итак: foo просто анализируется, чтобы быть в пакете KEYWORD, предполагая, что указание имени пакета перед именем символа означает по умолчанию пакет KEYWORD.

    нельзя назначать другое значение

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

    Помните: в Common Lisp символы принадлежат пакету. Это можно записать как:

    • foo, когда символ доступен в текущем пакете
    • foo: bar, когда символ FOO экспортируется из пакета BAR
    • foo :: bar, когда символ FOO - в пакете BAR

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

    Итак: foo просто анализируется, чтобы быть в пакете KEYWORD, предполагая, что указание имени пакета перед именем символа означает по умолчанию пакет KEYWORD.

    нельзя назначать другое значение

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

    Помните: в Common Lisp символы принадлежат пакету. Это можно записать как:

    • foo, когда символ доступен в текущем пакете
    • foo: bar, когда символ FOO экспортируется из пакета BAR
    • foo :: bar, когда символ FOO - в пакете BAR

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

    Итак: foo просто анализируется, чтобы быть в пакете KEYWORD, предполагая, что указание имени пакета перед именем символа означает по умолчанию пакет KEYWORD.

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

    Помните: в Common Lisp символы принадлежат пакету. Это можно записать как:

    • foo, когда символ доступен в текущем пакете
    • foo: bar, когда символ FOO экспортируется из пакета BAR
    • foo :: bar, когда символ FOO - в пакете BAR

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

    Итак: foo просто анализируется, чтобы быть в пакете KEYWORD, предполагая, что указание имени пакета перед именем символа означает по умолчанию пакет KEYWORD.

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

    Помните: в Common Lisp символы принадлежат пакету. Это можно записать как:

    • foo, когда символ доступен в текущем пакете
    • foo: bar, когда символ FOO экспортируется из пакета BAR
    • foo :: bar, когда символ FOO - в пакете BAR

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

    Итак: foo просто анализируется, чтобы быть в пакете KEYWORD, предполагая, что указание имени пакета перед именем символа означает по умолчанию пакет KEYWORD.

    когда символ FOO экспортируется из пакета BAR
  • foo :: bar, когда символ FOO находится в пакете BAR
  • Для символов ключевого слова это означает, что: foo, keyword: foo и keyword :: foo - все тот же символ. Таким образом, последние две нотации обычно не используются.

    Итак: foo просто анализируется, чтобы быть в пакете KEYWORD, предполагая, что указание имени пакета перед именем символа означает по умолчанию пакет KEYWORD.

    когда символ FOO экспортируется из пакета BAR
  • foo :: bar, когда символ FOO находится в пакете BAR
  • Для символов ключевого слова это означает, что: foo, keyword: foo и keyword :: foo - все тот же символ. Таким образом, последние две нотации обычно не используются.

    Итак: foo просто анализируется, чтобы быть в пакете KEYWORD, предполагая, что указание имени пакета перед именем символа означает по умолчанию пакет KEYWORD.

    29
    ответ дан 24 November 2019 в 01:01
    поделиться