All streams
Search
Write a publication
Pull to refresh
4
0
Send message

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

Как всегда, притянули за уши.


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

"Большинство разработчиков". Покажите мне этих разработчиков. Если человек использует const и до сих пор не понял, что это значит — либо разработчик никакой (передача по ссылке? это что такое?), либо никогда и не пробовал понять. Это проблема "большинства разработчиков", но никак не языка.


Однако код, написанный с его помощью, становится сложно понять, если, применяя такой оператор, начать использовать вложенные конструкции:
let conferenceCost = isStudent ? hasDiscountCode ? 25 : 50 : hasDiscountCode ? 100 : 200;


let conferenceCost = (
    isStudent ? (
        hasDiscountCode ? 25 : 50
    ) : (
        hasDiscountCode ? 100 : 200
    )
);

Так понятнее? Спагетти-код можно написать на любом языке.


let eventRecord = {
  user: { name: "Ben M", email: "ben@m.com" },
  event: "logged in",
  metadata: { date: "10-10-2017" },
  id: "123"
};
let {
  user: { name: userName = "Unknown" },
  event: eventType = "Unknown Event",
  metadata: {date: eventDate}, // кто-то опечатался
  id: eventId
} = obj;


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

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


function handlePost(post) {
    const [
        {name: authorName, email: authorEmail},
        ...moreAuthors
    ] = post.authors;
    // ...
}

Этот код понятен. Вот у нас есть пост, у него есть авторы, первого мы вынесем в переменные authorName и authorEmail, остальных запихнем в moreAuthors. А теперь тот-же код без rest/spread:


function handlePost(post) {
    const authorName = post.authors[0].name;
    const authorEmail = post.authors[0].email;
    const moreAuthors = post.authors.slice(1);
    // ...
}

Сильно понятнее? Сразу поймете, почему slice(1)? Ну… нет.


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

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


import {install as installPlugin1} from "./plugin1";
import {install as installPlugin2} from "./plugin2";
import {install as installPlugin3} from "./plugin3";

Или:


import installPlugin1 from "./plugin1";
import installPlugin2 from "./plugin2";
import installPlugin3 from "./plugin3";

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


Ну и еще пример: плагины подгружаются автоматически, через require.context, но иногда нужно получить определенные плагины:


Вариант с export function install:


const context = require.context("./plugins");
for(const name of context.keys()) {
    context(name).install();
}

...

import {install as installPlugin1} from "./plugin1";
import {install as installPlugin2} from "./plugin2";
import {install as installPlugin3} from "./plugin3";

Вариант с export function installPluginN:


const context = require.context("./plugins");
for(const name of context.keys()) {
    Object.values(context(name))[0]();
}

...

import {installPlugin1} from "./plugin1";
import {installPlugin2} from "./plugin2";
import {installPlugin3} from "./plugin3";

Вариант с export default function install:


const context = require.context("./plugins");
for(const name of context.keys()) {
    context(name).default(); // Ну или как-то иначе, если будет "import ... from '*.js'"
}

...

import installPlugin1 from "./plugin1";
import installPlugin2 from "./plugin2";
import installPlugin3 from "./plugin3";



Хватит топить JavaScript. У Вас половина статей про то, какой JS плохой и половина про том, какой JS хороший. Найдите другую тему (CSS Paint — хороший пример).

О, спасибо. Сослепу принял `elements[1:] == elements[:-1]` за `reverse`. Да и описание `перестановка элементов` вводит в заблуждение.
> 6. Одним из креативных подходов к решению этой задачи является перестановка элементов. Мы меняем элементы местами и проверяем, что список из-за этого не изменился. Это говорит нам о том, что все элементы в списке — одинаковые. Вот пару примеров такого подхода:

Палиндромы? Не, не слышали.
JavaScript обычно сокращается как JS, а не Js.
Идет. Есть драйвера PS/2, PCSpeaker, BGA, ATA, что-то под карты RealTek.

Опечатлся. Не arbitary, а arbitrary.


# добавить функцию в стэк для выполнения arbitrary python

Google Translate. Не, ну arbitary не переведенный — ладно, но стак? Знаю, что принято писать в личку, но это уже чересчур.

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

Кстати, не факт. Писал как-то свою реализацию Git и Mercurial. Так вот, Git никакие дельты не хранит, только gzip-ом сжимает.

Ещё его преимущество — можно отличить ситуации, когда -10 собрано как +0 и -10, и когда это +100500 -100510. Здесь же количество оценивших никак не отражается (насколько мне известно), и это низводит осмысленность такой оценки до минимума.

Если вы про комментарии, то наведите на их рейтинг и будет вам счастье.

Прошу прощения, если прочитал по диагонали и не заметил, но. Не рассказано самое интересное — staging area. Во многих системах контроля версий индекса нет. То, как вы описали команду add скорее похоже на mercurial.


В git никакие изменения сразу не регистрируются. Если вы изменили файл и запустили git commit, волшебство не произойдет. Вообще любые изменения нужно регистрировать git add — и создание, и изменение, и удаление файла. Изменения, добавленные git add — это и есть staging area. При это один файл может и быть, и не быть в staging area одновременно. Например (в консоли):


$ vi file.txt
$ git add file.txt
$ vi file.txt
$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)
        modified: file.txt

Changes not staged for commit:
  (use "git add/rm <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)
  (commit or discard the untracked or modified content in submodules)
        modified: file.txt
$ git commit # будет закоммичен первый файл

Ну и естественно можно изменения из staging area удалить.

  1. git log вместо log.
  2. В моей команде нужно экранирование кавычек, так как используется алиас. Вам нужно заменить \" на ", тогда заработает.

Если понравится, просто скопируйте мой команду.

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

Добавлять алиасы в гит нужно командой:


git config --global alias.d 'diff' # git d = git diff

Если первый символ команды — !, то остальная часть сткроки считается, как bash- (ну или что там у вас) команда:


git config --global alias.dc '!git d --cached' # git dc = git d --cached

Приходится использовать '!git', так как без ! не учитываются другие алиасы:


$ git config --global alias.dc 'd --cached'
$ git dc
git: 'dc' is not a git command. See 'git --help'.



git log --graph — просто он забавный. Не знаю, есть ли практическое применение.

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


log --graph --abbrev-commit --decorate --all --format=format:\"%C(bold blue)%h%C(reset) - %C(bold cyan)%aD%C(dim white) - %an%C(reset) %C(bold green)(%ar)%C(reset)%C(bold yellow)%d%C(reset)%n %C(white)%s%C(reset)\"

И легко можно понять, что 3f5c093 — мердж, что были смерджены изменения в DropDown и master-ветка, что 5a88259 — продолжение 62f349f, то есть ветка dropdown. А когда ветки разного цвета (на самом деле так и есть, просто в markdown нет цветов), еще понятнее.


| |  Pages: Make Pages.sections object of objects instead of object of arrays
* |   95874bc - Fri, 16 Jun 2017 21:44:19 +0300 - Ivanq (2 months ago)
|\ \   Merge branch 'dropdown' into design
| |/
| * 5a88259 - Fri, 16 Jun 2017 21:23:03 +0300 - Ivanq (2 months ago)
| |  DropDown: Don't make users use <select> and <option>
* | 09334af - Fri, 16 Jun 2017 21:28:27 +0300 - Ivanq (2 months ago)
| |  Includes: Get rid of <for>
* | 3b69065 - Fri, 16 Jun 2017 18:22:49 +0300 - Ivanq (3 months ago)
| |  UI.Page: Move section-specific styles to inc/{{section}}/index.css
| |  UI.Post: Show download button
* | 5c8ce85 - Fri, 16 Jun 2017 15:00:25 +0300 - Ivanq (3 months ago)
| |  UI.Post: Show additional info
* | 3921890 - Fri, 16 Jun 2017 15:00:12 +0300 - Ivanq (3 months ago)
| |  UI.Column: Pass platform, place and demoparty to <include>
* | f555f9f - Fri, 16 Jun 2017 14:59:30 +0300 - Ivanq (3 months ago)
| |  Includes: Allow passing objects to <include>
* |   3f5c093 - Fri, 16 Jun 2017 14:58:43 +0300 - Ivanq (3 months ago)
|\ \   Merge branch 'dropdown' into design
| |/
| * 62f349f - Fri, 16 Jun 2017 14:58:32 +0300 - Ivanq (3 months ago)
| |  DropDown: Pass native <select> to constructor instead of <div>
* | c14f018 - Fri, 16 Jun 2017 14:56:50 +0300 - Ivanq (3 months ago)
| |  Translate: Implement Translate::place() and Translate::ordinal()
* | c984efc - Fri, 16 Jun 2017 12:19:27 +0300 - Ivanq (3 months ago)
| |  UI.News: Update news font
* |   3463a02 - Fri, 16 Jun 2017 11:05:11 +0300 - Ivanq (3 months ago)
|\ \   Merge branch 'dropdown' into design
| |/
| * 6b5d202 - Fri, 16 Jun 2017 10:55:35 +0300 - Ivanq (3 months ago)
| |  DropDown: Fire 'change' event
| * 8864ea3 - Thu, 15 Jun 2017 21:57:41 +0300 - Ivanq (3 months ago)
|/   DropDown: Add
* ac2380d - Thu, 15 Jun 2017 19:19:46 +0300 - Ivanq (3 months ago)
|  UI.Column: Show section name
* 5faebfa - Thu, 15 Jun 2017 19:19:34 +0300 - Ivanq (3 months ago)
|  Translate: Add Translate::section()
Ставим пакеты для LaTeX. Пример:
sudo apt-get install  texmaker gummi texlive texlive-full texlive-latex-recommended latexdraw intltool-debian lacheck libgtksourceview2.0-0 libgtksourceview2.0-common lmodern luatex po-debconf tex-common texlive-binaries texlive-extra-utils texlive-latex-base texlive-latex-base-doc texlive-luatex texlive-xetex texlive-lang-cyrillic texlive-fonts-extra texlive-science texlive-latex-extra texlive-pstricks

Напомнило

К счастью, sed позволяет нам самостоятельно задавать символы-разделители для использования их в команде замены. Разделителем считается первый символ, который будет встречен после s:
$ sed 's!/bin/bash!/bin/csh!' /etc/passwd

Information

Rating
Does not participate
Registered
Activity