Spec-Zone.ru › Julia 0.6

Заметные отличия от других языков

Заметные отличия от MATLAB

Хотя пользователи MATLAB могут найти синтаксис Julia знакомым, Julia не является клоном MATLAB. Существуют значительные синтаксические и функциональные различия. Ниже приведены некоторые заметные отличия, которые могут поставить в тупик пользователей Julia, привыкших к MATLAB:

  • Массивы Julia индексируются с помощью квадратных скобок, A[i,j].

  • Массивы Julia присваиваются по ссылке. После A=B, изменение элементов B также изменит A.

  • Значения Julia передаются и присваиваются по ссылке. Если функция изменяет массив, изменения будут видны в вызывающей функции.

  • Julia не увеличивает автоматически массивы в операторе присваивания. В то время как в MATLAB a(4) = 3.2 может создать массив a = [0 0 0 3.2] и a(5) = 7 может увеличить его до a = [0 0 0 3.2 7], соответствующий оператор Julia a[5] = 7 выдаст ошибку, если длина a меньше 5 или если это первое использование идентификатора a. В Julia есть push!() и append!(), которые увеличивают Vector намного эффективнее, чем a(end+1) = val MATLAB.

  • Мнимая единица sqrt(-1) представлена в Julia как im, а не i или j, как в MATLAB.

  • В Julia, литеральные числа без десятичной точки (например, 42) создают целые числа вместо чисел с плавающей запятой. Поддерживаются произвольно большие целочисленные литералы. В результате некоторые операции, такие как 2^-1, могут вызвать ошибку области значений, так как результат не является целым числом (см. статью FAQ об ошибках области значений для получения подробностей).

  • В Julia, несколько значений возвращаются и присваиваются как кортежи, например, (a, b) = (1, 2) или a, b = 1, 2. MATLAB's nargout, часто используемый в MATLAB для выполнения необязательной работы на основе количества возвращаемых значений, в Julia не существует. Вместо этого пользователи могут использовать необязательные и ключевые аргументы для достижения аналогичных возможностей.

  • Julia имеет истинные одномерные массивы. Столбцовые векторы имеют размер N, а не Nx1. Например, rand(N) создает одномерный массив.

  • В Julia [x,y,z] всегда создает массив из 3 элементов, содержащих x, y и z.

    • Для конкатенации по первому ("вертикальному") измерению используйте либо vcat(x,y,z), либо разделяйте точкой с запятой ([x; y; z]).

    • Для конкатенации по второму ("горизонтальному") измерению используйте либо hcat(x,y,z), либо разделяйте пробелами ([x y z]).

    • Для создания блочных матриц (конкатенация по двум первым измерениям) используйте либо hvcat(), либо сочетание пробелов и точек с запятой ([a b; c d]).

  • В Julia a:b и a:b:c создают объекты Range. Для создания полного вектора, как в MATLAB, используйте collect(a:b). Как правило, вызов collect не требуется. Range в большинстве случаев будет вести себя как обычный массив, но является более эффективным, потому что лениво вычисляет свои значения. Эта модель создания специализированных объектов вместо полных массивов часто используется и также встречается в функциях, таких как linspace, или с итераторами, такими как enumerate и zip. Специализированные объекты в основном можно использовать как обычные массивы.

  • Функции в Julia возвращают значения из последнего выражения или ключевого слова return вместо перечисления имен переменных для возврата в определении функции (см. Ключевое слово return для получения подробностей).

  • Скрипт Julia может содержать любое количество функций, и все определения будут видимыми снаружи при загрузке файла. Определения функций могут загружаться из файлов вне текущей рабочей директории.

  • В Julia, операции сведения, такие как sum(), prod() и max(), выполняются над каждым элементом массива при вызове с одним аргументом, как в sum(A), даже если у A более одного измерения.

  • В Julia, функции, такие как sort(), которые по умолчанию работают по столбцам (sort(A) эквивалентно sort(A,1)), не имеют специального поведения для массивов 1xN; аргумент возвращается без изменений, так как он по-прежнему выполняет sort(A,1). Чтобы отсортировать матрицу 1xN как вектор, используйте sort(A,2).

  • В Julia, если A является двумерным массивом, fft(A) вычисляет 2D-преобразование Фурье. В частности, это не эквивалентно fft(A,1), которое вычисляет 1D-преобразование Фурье, действуя по столбцам.

  • В Julia, для вызова функций с нулевыми аргументами, необходимо использовать скобки, как в tic() и toc().

  • В Julia не рекомендуется использовать точки с запятой для завершения операторов. Результаты операторов не выводятся автоматически (за исключением интерактивного приглашения), и строки кода не нужно завершать точкой с запятой. println() или @printf() могут быть использованы для вывода определенного вывода.

  • В Julia, если A и B являются массивами, логические операции сравнения, такие как A == B, не возвращают массив булевых значений. Вместо этого используйте A .== B, аналогично для других булевых операторов, таких как <, > и =.

  • В Julia, операторы &, | и ⊻ (xor) выполняют побитовые операции, эквивалентные and, or и xor соответственно в MATLAB, и имеют приоритет, аналогичный побитовым операторам Python (в отличие от C). Они могут работать с скалярами или поэлементно в массивах и могут использоваться для объединения логических массивов, но обратите внимание на разницу в порядке операций: скобки могут потребоваться (например, чтобы выбрать элементы A равные 1 или 2, используйте (A .== 1) | (A .== 2)).

  • Элементы коллекции в Julia могут быть переданы в функцию в качестве аргументов с использованием оператора splat ..., как в xs=[1,2]; f(xs...).

  • Julia's svd() возвращает сингулярные значения как вектор, а не как плотную диагональную матрицу.

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

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

  • Структуры данных Julia не поддерживают динамическое добавление полей во время выполнения, в отличие от структур MATLAB. Вместо этого используйте Dict.

  • Каждый модуль в Julia имеет собственное глобальное пространство имен/область видимости, в то время как в MATLAB есть только одно глобальное пространство имен.

  • В MATLAB, стандартный способ удаления нежелательных значений — использование логической индексации, как в выражении x(x>3) или в операторе x(x>3) = [] для изменения x на месте. В отличие от этого, Julia предоставляет функции высшего порядка filter() и filter!(), позволяющие пользователям написать filter(z->z>3, x) и filter!(z->z>3, x) как альтернативы соответствующим переводам x[x.>3] и x = x[x.>3]. Использование filter!() снижает использование временных массивов.

  • Аналог извлечения (или "развертки") всех элементов ячейкового массива, например, в vertcat(A{:}) в MATLAB, записывается с использованием оператора splat в Julia, например, как vcat(A...).

Заметные отличия от R

Одна из целей Julia — предоставить эффективный язык для анализа данных и статистического программирования. Для пользователей, переходящих из R в Julia, вот некоторые заметные отличия:

  • Одинарные кавычки в Julia обозначают символы, а не строки.

  • В Julia можно создавать подстроки, индексируя строки. В R строки необходимо преобразовать в векторы символов перед созданием подстрок.

  • В Julia, как и в Python, но в отличие от R, строки можно создавать с помощью тройных кавычек """ ... """. Этот синтаксис удобен для создания строк, содержащих переводы строк.

  • В Julia аргументы переменной длины (varargs) задаются с использованием оператора разброса ..., который всегда следует за именем конкретной переменной, в отличие от R, для которого ... может встречаться изолированно.

  • В Julia оператор остатка (модуль) — это mod(a, b), а не a %% b. % в Julia — это оператор нахождения остатка.

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

    • В R, c(1, 2, 3, 4)[c(TRUE, FALSE)] эквивалентно c(1, 3).

    • В R, c(1, 2, 3, 4)[c(TRUE, FALSE, TRUE, FALSE)] эквивалентно c(1, 3).

    • В Julia, [1, 2, 3, 4][[true, false]] вызывает ошибку BoundsError.

    • В Julia, [1, 2, 3, 4][[true, false, true, false]] производит [1, 3].

  • Как и во многих языках программирования, Julia не всегда позволяет выполнять операции над векторами разной длины, в отличие от R, где векторам нужно только иметь общую область индексов. Например, c(1, 2, 3, 4) + c(1, 2) является допустимым кодом в R, но эквивалентный [1, 2, 3, 4] + [1, 2] вызовет ошибку в Julia.

  • Функция map() в Julia принимает функцию первой, а затем её аргументы, в отличие от lapply(<structure>, function, ...) в R. Аналогично, эквивалент apply(X, MARGIN, FUN, ...) в R в Julia — это mapslices(), где функция является первым аргументом.

  • Многомерное применение в R, например, mapply(choose, 11:13, 1:3), можно записать как broadcast(binomial, 11:13, 1:3) в Julia. Аналогично, Julia предлагает более короткий точечный синтаксис для векторизации функций binomial.(11:13, 1:3).

  • Julia использует end для обозначения конца блоков условных операторов, как if, циклов, как while/ for, и функций. Вместо однострочного if ( cond ) statement Julia допускает операторы вида if cond; statement; end, cond && statement и !cond || statement. Операторы присваивания в последних двух синтаксисах должны быть явно заключены в скобки, например, cond && (x = value).

  • В Julia операторы <-, <<- и -> не являются операторами присваивания.

  • -> в Julia создаёт анонимную функцию, как в Python.

  • Julia строит векторы, используя квадратные скобки. [1, 2, 3] в Julia эквивалентно c(1, 2, 3) в R.

  • * оператор в Julia может выполнять умножение матриц, в отличие от R. Если A и B — матрицы, то A * B обозначает умножение матриц в Julia, что эквивалентно A %*% B в R. В R тот же самый оператор выполнит поэлементное (Хэдэмэрдовое) произведение. Чтобы получить поэлементное умножение, в Julia нужно написать A .* B.

  • Julia выполняет транспонирование матриц с помощью оператора .' и сопряжённого транспонирования с помощью оператора '. A.' в Julia эквивалентно t(A) в R.

  • В Julia скобки не требуются при записи операторов if или циклов for/while: используйте for i in [1, 2, 3] вместо for (i in c(1, 2, 3)) и if i == 1 вместо if (i == 1).

  • В Julia числа 0 и 1 не рассматриваются как булевы значения. Нельзя написать if (1) в Julia, так как операторы if принимают только булевы значения. Вместо этого можно написать if true, if Bool(1) или if 1==1.

  • В Julia нет nrow и ncol. Вместо этого используйте size(M, 1) для nrow(M) и size(M, 2) для ncol(M).

  • Julia тщательно различает скаляры, векторы и матрицы. В R, 1 и c(1) — одно и то же. В Julia они не могут быть использованы взаимозаменяемо.

  • diag и diagm в Julia отличаются от аналогичных функций в R.

  • В Julia нельзя присвоить значение результату вызова функции в левой части оператора присваивания: нельзя написать diag(M) = ones(n).

  • В Julia не рекомендуется заполнять главный пространство имён функциями. Большинство статистических функций Julia находятся в пакетах в рамках организации JuliaStats. Например:

    • Функции, относящиеся к распределениям вероятностей, предоставляются пакетом Distributions.

    • Пакет DataFrames предоставляет структуры данных DataFrame.

    • Обобщённые линейные модели предоставляются пакетом GLM.

  • Julia поддерживает кортежи и хэш-таблицы, но не списки в стиле R. При возвращении нескольких значений обычно следует использовать кортеж: вместо list(a = 1, b = 2) используйте (1, 2).

  • Julia поощряет создание собственных типов, которые проще в использовании, чем объекты S3 или S4 в R. Система множественного диспетчеризации Julia означает, что table(x::TypeA) и table(x::TypeB) ведут себя как table.TypeA(x) и table.TypeB(x) в R.

  • В Julia значения передаются и присваиваются по ссылке. Если функция изменяет массив, изменения будут видны в вызывающей функции. Это сильно отличается от R и позволяет новым функциям работать с большими структурами данных значительно эффективнее.

  • В Julia векторы и матрицы конкатенируются с помощью hcat(), vcat() и hvcat(), а не c, rbind и cbind, как в R.

  • В Julia диапазон, подобный a:b, не является сокращённой записью вектора, как в R, а является специализированным Range, используемым для итерации без высокой нагрузки на память. Для преобразования диапазона в вектор используйте collect(a:b).

  • max() и min() в Julia эквивалентны pmax и pmin соответственно в R, но оба аргумента должны иметь одинаковые размеры. Хотя maximum() и minimum() заменяют max и min в R, существуют важные различия.

  • sum(), prod(), maximum() и minimum() в Julia отличаются от своих аналогов в R. Все они принимают один или два аргумента. Первый аргумент — это итерируемая коллекция, например, массив. Если есть второй аргумент, то этот аргумент указывает на размерности, по которым выполняется операция. Например, пусть A=[[1 2],[3 4]] в Julia и B=rbind(c(1,2),c(3,4)) — та же самая матрица в R. Тогда sum(A) даёт тот же результат, что и sum(B), но sum(A, 1) — это строковый вектор, содержащий сумму по каждому столбцу, а sum(A, 2) — это столбцовый вектор, содержащий сумму по каждой строке. Это отличается от поведения в R, где sum(B,1)=11 и sum(B,2)=12. Если второй аргумент — вектор, то он задаёт все размерности, по которым выполняется суммирование, например, sum(A,[1,2])=10. Следует отметить, что нет проверки на корректность второго аргумента.

  • В Julia есть несколько функций, которые могут изменять свои аргументы. Например, есть как sort(), так и sort!().

  • В R для повышения производительности требуется векторизация. В Julia практически всё наоборот: наилучшие результаты часто достигаются с помощью девекторизованных циклов.

  • Julia использует жадное вычисление и не поддерживает ленивые вычисления в стиле R. Для большинства пользователей это означает, что существует очень мало нецитируемых выражений или имён столбцов.

  • В Julia нет типа данных NULL.

  • В Julia нет аналогов assign или get из R.

  • В Julia оператор return не требует скобок.

  • В R идиоматичный способ удаления нежелательных значений — использование логической индексации, как в выражении x[x>3] или в операторе x = x[x>3] для изменения x на месте. В отличие от этого, Julia предоставляет функции более высокого порядка filter() и filter!(), что позволяет пользователям писать filter(z->z>3, x) и filter!(z->z>3, x) в качестве альтернатив соответствующим переведённым операциям x[x.>3] и x = x[x.>3]. Использование filter!() сокращает использование временных массивов.

Важные отличия от Python

  • Julia требует end для завершения блока. В отличие от Python, в Julia нет ключевого слова pass.

  • В Julia индексация массивов, строк и т. д. основана на 1, а не на 0.

  • Индексация срезов в Julia включает последний элемент, в отличие от Python. a[2:3] в Julia соответствует a[1:3] в Python.

  • Julia не поддерживает отрицательные индексы. В частности, последний элемент списка или массива индексируется с помощью end в Julia, а не -1, как в Python.

  • Блоки for, if, while и т. д. в Julia завершаются ключевым словом end. Уровень отступа не имеет значения, как в Python.

  • В Julia нет синтаксиса продолжения строк: если в конце строки введенное выражение является полным, оно считается завершенным; в противном случае ввод продолжается. Один из способов заставить выражение продолжить — заключить его в скобки.

  • Массивы Julia являются столбцово-главными (упорядоченными по Фортрану), тогда как массивы NumPy по умолчанию являются строково-главными (упорядоченными по C). Для достижения оптимальной производительности при итерации по массивам порядок циклов в Julia должен быть обратным по сравнению с NumPy (см. соответствующий раздел Рекомендаций по производительности).

  • Операторы обновления Julia (например, +=, -=, ...) являются не локальными, в отличие от операторов NumPy. Это означает, что A = ones(4); B = A; B += 3 не изменяет значения в A, а скорее привязывает имя B к результату правой части B = B + 3, который является новым массивом. Используйте B[:] += 3, явные циклы или InplaceOps.jl.

  • Julia вычисляет значения аргументов по умолчанию функций каждый раз при вызове метода, в отличие от Python, где значения по умолчанию вычисляются только один раз при определении функции. Например, функция f(x=rand()) = x возвращает новое случайное число каждый раз при вызове без аргумента. С другой стороны, функция g(x=[1,2]) = push!(x,3) возвращает [1,2,3] каждый раз при вызове как g().

  • В Julia % — это оператор остатка, а в Python — оператор модуля.

Заметные различия с C/C++

  • Массивы Julia индексируются квадратными скобками и могут иметь более одной размерности A[i,j]. Этот синтаксис не является просто синтаксическим сахаром для ссылки на указатель или адрес, как в C/C++. Обратитесь к документации Julia для синтаксиса построения массивов (он изменялся между версиями).

  • В Julia индексация массивов, строк и т. д. основана на 1, а не на 0.

  • Массивы Julia присваиваются по ссылке. После A=B изменение элементов B также изменит A. Операторы обновления, такие как +=, не работают на месте, они эквивалентны A = A + B, что перепривязывает левую часть к результату выражения правой части.

  • Массивы Julia имеют порядок следования по столбцам (порядок Fortran), тогда как массивы C/C++ по умолчанию имеют порядок следования по строкам. Для достижения оптимальной производительности при циклическом переборе массивов порядок циклов в Julia должен быть обратным по отношению к C/C++ (см. соответствующий раздел Рекомендации по производительности).

  • Значения Julia передаются и присваиваются по ссылке. Если функция изменяет массив, изменения будут видны в вызывающей функции.

  • В Julia пробелы имеют значение, в отличие от C/C++, поэтому при добавлении/удалении пробелов из программы Julia необходимо соблюдать осторожность.

  • В Julia целочисленные литералы без десятичной точки (например, 42) создают целые числа со знаком, типа Int, но литералы, слишком большие для размера машинного слова, автоматически будут повышены до типа большего размера, например, Int64 (если Int является Int32), Int128 или произвольно большого типа BigInt. Нет числовых суффиксов литералов, таких как L, LL, U, UL, ULL, чтобы указывать беззнаковые и/или со знаком/без знака. Десятичные литералы всегда со знаком, а шестнадцатеричные литералы (начинающиеся с 0x, как в C/C++), — беззнаковые. Шестнадцатеричные литералы также, в отличие от C/C++/Java и в отличие от десятичных литералов в Julia, имеют тип, основанный на длине литерала, включая ведущие нули. Например, 0x0 и 0x00 имеют тип UInt8, 0x000 и 0x0000 имеют тип UInt16, затем литералы с 5 до 8 шестнадцатеричных цифр имеют тип UInt32, 9 до 16 шестнадцатеричных цифр имеют тип UInt64, а 17 до 32 шестнадцатеричных цифр имеют тип UInt128. Это нужно учитывать при определении шестнадцатеричных масок, например, ~0xf == 0xf0 сильно отличается от ~0x000f == 0xfff0. 64-битные Float64 и 32-битные Float32 битовые литералы выражаются как 1.0 и 1.0f0 соответственно. Литералы с плавающей запятой округляются (а не повышаются до типа BigFloat), если они не могут быть точно представлены. Литералы с плавающей запятой по поведению ближе к C/C++. Восьмеричные (с префиксом 0o) и двоичные (с префиксом 0b) литералы также обрабатываются как беззнаковые.

  • Строковые литералы могут быть ограничены либо " или """, """ ограниченные литералы могут содержать " символы без их цитирования, например, "\"". Строковые литералы могут содержать значения других переменных или выражений, интерполированных в них, что указывается $variablename или $(expression), которые оценивают имя переменной или выражение в контексте функции.

  • // обозначает Rational число, а не однострочный комментарий (который является # в Julia).

  • #= обозначает начало многострочного комментария, а =# завершает его.

  • Функции в Julia возвращают значения из последнего выражения(ий) или ключевого слова return. Из функций можно возвращать несколько значений и присваивать их как кортежи, например, (a, b) = myfunction() или a, b = myfunction(), вместо того, чтобы передавать указатели на значения, как это необходимо в C/C++ (то есть, a = myfunction(&b)).

  • Julia не требует использования точки с запятой для завершения операторов. Результаты выражений не выводятся автоматически (за исключением интерактивного приглашения, т. е. REPL), и строки кода не должны заканчиваться точкой с запятой. println() или @printf() можно использовать для вывода определенного вывода. В REPL ; можно использовать для подавления вывода. ; также имеет другое значение в [ ], на что следует обратить внимание. ; может использоваться для разделения выражений в одной строке, но в большинстве случаев это не строго необходимо и является скорее средством повышения удобочитаемости.

  • В Julia оператор ⊻ (xor) выполняет побитовое XOR-действие, т. е. ^ в C/C++. Кроме того, приоритет побитовых операторов отличается от C/++, поэтому могут потребоваться скобки.

  • Оператор Julia ^ — возведение в степень (pow), а не побитовое XOR, как в C/C++ (используйте ⊻ или xor в Julia).

  • В Julia есть два оператора сдвига вправо, >> и >>>. >>> выполняет арифметический сдвиг, >> всегда выполняет логический сдвиг, в отличие от C/C++, где смысл >> зависит от типа сдвигаемого значения.

  • -> Julia создает анонимную функцию, она не обращается к члену через указатель.

  • В Julia скобки не нужны при написании операторов if или циклов for/while: используйте for i in [1, 2, 3] вместо for (int i=1; i <= 3; i++) и if i == 1 вместо if (i == 1).

  • Julia не рассматривает числа 0 и 1 как булевы. Вы не можете написать if (1) в Julia, потому что операторы if принимают только булевы значения. Вместо этого вы можете написать if true, if Bool(1) или if 1==1.

  • Julia использует end для обозначения конца блоков условных операторов, таких как if, циклических блоков, таких как while/ for, и функций. Вместо однострочного if ( cond ) statement Julia позволяет использовать операторы вида if cond; statement; end, cond && statement и !cond || statement. Операторы присваивания в последних двух синтаксисах должны быть явно заключены в скобки, например, cond && (x = value), из-за приоритета операторов.

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

  • Макросы Julia работают с разобранными выражениями, а не с текстом программы, что позволяет им выполнять сложные преобразования кода Julia. Имена макросов начинаются с символа @ и имеют как синтаксис функций @mymacro(arg1, arg2, arg3), так и синтаксис операторов @mymacro arg1 arg2 arg3. Формы взаимозаменяемы; функция-подобная форма особенно полезна, если макрос появляется в другом выражении и часто является более ясной. Оператор-подобная форма часто используется для аннотирования блоков, как в параллельном for конструкте: @parallel for i in 1:n; #= body =#; end. В тех случаях, когда конец конструкции макроса может быть неясным, используйте функцию-подобную форму.

  • В Julia теперь есть тип перечисления, выраженный с помощью макроса @enum(name, value1, value2, ...). Например: @enum(Fruit, banana=1, apple, pear)

  • По соглашению функции, которые изменяют свои аргументы, имеют суффикс ! в конце имени, например, push!.

  • В C++, по умолчанию, используется статическая диспетчеризация, т. е. необходимо пометить функцию как виртуальную, чтобы иметь динамическую диспетчеризацию. С другой стороны, в Julia каждый метод является «виртуальным» (хотя это более общее понятие, так как методы диспетчеризируются по типу каждого аргумента, а не только this, с использованием правила наиболе специализированного объявления).

© 2009–2016 Jeff Bezanson, Stefan Karpinski, Viral B. Shah, and other contributors
Licensed under the MIT License.
https://docs.julialang.org/en/release-0.6/manual/noteworthy-differences/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API