Есть ли хорошие альтернативы GarageBand?

У владельца были некоторые коммиты на то, что они не толкали, затем бежали git pull и извлекали / сливались в новые коммиты от разработки, которые были в удаленном репо.

6
задан coversnail 13 May 2012 в 14:22
поделиться

13 ответов

Это зависит от:

  • Требуется ли высокая производительность
  • Читаемость цикла
  • Является ли алгоритм сложным

Если цикл не является узким местом, а алгоритм прост (например, for_each), то для текущего стандарта C ++ я бы предпочел свернутый вручную цикл для удобства чтения. (Локальность логики является ключевой.)

Однако теперь, когда C ++ 0x / C ++ 11 поддерживается некоторыми крупными компиляторами, я бы сказал, использовать алгоритмы STL, потому что они теперь допускают лямбда-выражения - и, таким образом, локальность логики.

19
ответ дан Jonathan Leffler 15 October 2019 в 15:41
поделиться

Смелость (устанавливаемый в Центре программного обеспечения) является, вероятно, самой близкой к тому, что Вы хотите. Это обеспечивает большую часть функциональности, которую Вы перечислили, за исключением редактирования MIDI.

Для редактирования MIDI я предложил бы Арию Maestosa, хотя это в настоящее время не упаковывается для Ubuntu, таким образом, Вы будете, вероятно, иметь к загрузка и создадите источник .

2
ответ дан Eliah Kagan 22 October 2019 в 14:34
поделиться

std::foreach - это тот код, который заставил меня проклинать STL много лет назад.

Я не могу сказать, лучше ли это, но мне больше нравится иметь код моего цикла в преамбуле цикла. Для меня это строгое требование . И конструкция std::foreach не позволит мне этого (как ни странно, версии Java или C # для foreach - это круто, насколько я могу судить ... Итак, я думаю, это подтверждает, что для меня локальность тела цикла очень очень важно).

Так что я буду использовать foreach, только если есть уже читаемый / понятный алгоритм, который можно использовать с ним. Если нет, нет, я не буду. Но это вопрос вкуса, я полагаю, поскольку мне, возможно, следует постараться понять и научиться разбирать все это ...

Заметьте, что люди, находящиеся в активном усилении, по-видимому, чувствовали себя примерно так же, поскольку они написали BOOST_FOREACH:

#include <string>
#include <iostream>
#include <boost/foreach.hpp>

int main()
{
    std::string hello( "Hello, world!" );

    BOOST_FOREACH( char ch, hello )
    {
        std::cout << ch;
    }

    return 0;
}

См .: http://www.boost.org/doc/libs/1_35_0 /doc/html/foreach.html

8
ответ дан paercebal 15 October 2019 в 15:41
поделиться

Это - действительно одна вещь, которую понял превратно Scott Meyers.

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

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

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

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

6
ответ дан 15 October 2019 в 15:41
поделиться

Цикл for является обязательным, алгоритмы декларативными. Когда вы пишете std::max_element, очевидно, что вам нужно, когда вы используете цикл для достижения того же самого, это не обязательно так.

Алгоритмы также могут иметь небольшое преимущество в производительности. Например, при обходе std::deque специализированный алгоритм может избежать избыточной проверки того, перемещает ли данный инкремент указатель за границу фрагмента.

Однако сложные выражения функторов быстро делают вызовы алгоритма нечитаемыми. Если явный цикл более читабелен, используйте его. Если вызов алгоритма может быть выражен без десятиуровневых выражений связывания, то все равно предпочитайте его. Читаемость здесь важнее, чем производительность , здесь , потому что этот вид оптимизации - то, что Кнут так классно приписывает Хоару; вы сможете без проблем использовать другую конструкцию, если поймете, что это узкое место.

4
ответ дан Roman Odaisky 15 October 2019 в 15:41
поделиться

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

Для алгоритмов, которые берут функторы, обычно не, пока C++ 0x лямбды не может использоваться. Если функтор является маленьким, и алгоритм сложен (большинство не), тогда, может быть лучше все еще использовать алгоритм станд.

3
ответ дан Greg Rogers 15 October 2019 в 15:41
поделиться

Я большой поклонник алгоритмов STL в принципе , но на практике это слишком громоздко. К тому времени, когда вы определите свои классы функторов / предикатов, две строки цикла могут превратиться в 40+ строк кода, которые внезапно будут в 10 раз сложнее понять.

К счастью, в C ++ 0x будет проще на тонну с лямбда-функциями, auto и новым for синтаксисом. Оформить заказ Обзор C ++ 0x в Википедии.

3
ответ дан Pat Notz 15 October 2019 в 15:41
поделиться

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

, Например, я не поместил бы что-то как

for (int i = 0; i < some_vector.size(); i++)
    if (some_vector[i] == NULL) some_other_vector[i]++;

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

существует много других примеров, где использование алгоритмов STL имеет много смысла, но необходимо выбрать индивидуальное основание.

2
ответ дан Maximilian 15 October 2019 в 15:41
поделиться

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

Насколько эффективнее стандарт для цикла над вектором:

int weighted_sum = 0;
for (int i = 0; i < a_vector.size(); ++i) {
  weighted_sum += (i + 1) * a_vector[i];  // Just writing something a little nontrivial.
}

, чем использование конструкции for_each или попытка вписать это в вызов накопления?

Вы могли бы утверждают, что итерационный процесс менее эффективен, но для каждого каждый также вводит вызов функции на каждом шаге (который может можно уменьшить, пытаясь встроить функцию, но помните, что «встроенный» является лишь предположением компилятору - он может игнорировать его).

В любом случае разница невелика. По моему опыту, более 90% кода, который вы пишете, не критичны по производительности, но критично по времени кодера . Сохраняя ваш цикл STL буквально встроенным, он очень читабелен. Меньше косвенности, чтобы споткнуться, для себя или будущих сопровождающих. Если это в вашем руководстве по стилю, то вы экономите некоторое время на учебе для своих кодеров (признайте, что обучение правильному использованию STL в первый раз требует нескольких моментов). Это последнее, что я имею в виду под ценой возможности записи.

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

2
ответ дан Tyler 15 October 2019 в 15:41
поделиться

Я думаю, что важным фактором является уровень комфорта разработчика.

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

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

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

0
ответ дан JohnMcG 15 October 2019 в 15:41
поделиться

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

sudo apt install ardour

screenshot

5
ответ дан Pablo A 22 October 2019 в 14:34
поделиться

IMO, a lot of standard library algorithms like std::for_each should be avoided - mainly for the lack-of-lambda issues mentioned by others, but also because there's such a thing as inappropriate hiding of details.

Of course hiding details away in functions and classes is all part of abstraction, and in general a library abstraction is better than reinventing the wheel. But a key skill with abstraction is knowing when to do it - and when not to do it. Excessive abstraction can damage readability, maintainability etc. Good judgement comes with experience, not from inflexible rules - though you must learn the rules before you learn to break them, of course.

OTOH, it's worth considering the fact that a lot of programmers have been using C++ (and before that, C, Pascal etc) for a long time. Old habits die hard, and there is this thing called cognitive dissonance which often leads to excuses and rationalisations. Don't jump to conclusions, though - it's at least as likely that the standards guys are guilty of post-decisional dissonance.

1
ответ дан 28 November 2019 в 06:51
поделиться

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

Давайте возьмем пример. Здесь у нас есть группа детей, и мы хотим установить их "Foo Count" на некоторое значение. Стандартным итерационным подходом является:

for (vector<Child>::iterator iter = children.begin();
    iter != children.end();
    ++iter)
{
    iter->setFooCount(n);
}

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

for_each(children.begin(), children.end(), SetFooCount(n));

Вау, это говорит именно о том, что нам нужно. Вам не нужно разгадывать, вы сразу же знаете, что он устанавливает "Foo Count" для каждого ребенка. (Было бы еще яснее, если бы нам не нужна была .begin() / .end() ерунда, но вы не можете иметь все, и они не посоветовались со мной, когда делали STL).

Конечно, вам нужно определить этот волшебный functor, SetFooCount, но его определение довольно простое:

class SetFooCount
{
public:
    SetFooCount(int n) : fooCount(n) {}

    void operator () (Child& child)
    {
        child.setFooCount(fooCount);
    }

private:
    int fooCount;
};

В общем, это больше кода, и вы должны посмотреть в другом месте, чтобы узнать, что именно делает SetFooCount. Но так как мы его хорошо назвали, то 99% времени нам не нужно смотреть на код для SetFooCount. Мы предполагаем, что он делает то, что говорит, и нам нужно смотреть только на строку for_each.

Что мне действительно нравится, так это то, что использование алгоритмов приводит к смещению парадигмы. Вместо того, чтобы думать о списке, как о коллекции объектов, и делать что-то с каждым элементом списка, вы думаете о списке, как о первоклассном сущности, и работаете непосредственно с самим списком. Через список происходит итерация for-loop, вызывая функцию-член для каждого элемента, чтобы установить Foo Count. Вместо этого я выполняю одну команду, которая устанавливает Foo Count для каждого элемента списка. Это тонко, но когда вы смотрите на лес, а не на деревья, вы получаете больше мощности.

Итак, при небольшом обдумывании и тщательном именовании, мы можем использовать алгоритмы STL, чтобы сделать более чистый, ясный код, и начать думать на менее гранулированном уровне.

9
ответ дан 28 November 2019 в 06:51
поделиться
Другие вопросы по тегам:

Похожие вопросы: