Spec-Zone.ru › Julia 0.5

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

Заметные различия от 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 v0.3 конкатенация скаляров и массивов с синтаксисом [x,y,z] выполняется по первой размерности («по вертикали»). Для конкатенации по второй размерности («по горизонтали») используйте пробелы, как в [x y z]. Для построения блочных матриц (конкатенация по двум первым размерностям) используется синтаксис [a b; c d] для избежания путаницы. В Julia v0.4 синтаксис конкатенации [x, [y, z]] устарел в пользу синтаксиса [x; [y, z]].
  • В 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 операторы &, | и $ выполняют побитовые операции, эквивалентные 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 type не поддерживают динамическое добавление полей во время выполнения, в отличие от MATLAB’s classes. Вместо этого используйте 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) задаются с помощью оператора splat ..., который всегда следует за именем конкретной переменной, в отличие от 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:4] + [1:2] вызовет ошибку в Julia.
  • Оператор apply() в Julia принимает функцию первой, а затем её аргументы, в отличие от lapply(<structure>, function, arg2, ...) в R.
  • 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 этот же символ обозначает поэлементное (хадамардовое) произведение. Чтобы получить поэлементное умножение, нужно записать A .* B в Julia.
  • 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 их нельзя использовать взаимозаменяемо. Потенциально путающий результат заключается в том, что x' * y для векторов x и y — это вектор из одного элемента, а не скаляр. Чтобы получить скаляр, используйте dot(x, y).
  • Функции diag() и diagm() в Julia отличаются от аналогичных функций в R.
  • В Julia нельзя присвоить значение результату вызова функции в левой части оператора присваивания: нельзя написать diag(M) = ones(n).
  • В Julia не рекомендуется заполнять основной пространство имён функциями. Большая часть статистических функций Julia находится в пакетах в рамках организации JuliaStats. Например:
    • Функции, относящиеся к распределениям вероятностей, предоставляются пакетом Distributions.
    • Пакет DataFrames предоставляет структуры данных DataFrames.
    • Обобщённые линейные модели предоставляются пакетом 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, но представляет собой специализированный объект, используемый для итерации без высокой загрузки памяти. Чтобы преобразовать диапазон в вектор, используйте 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 вектор векторов может автоматически конкатенироваться в одномерный вектор если не указан явный тип элементов. Например:
    • В Julia, [1, [2, 3]] конкатенируется в [1, 2, 3], как в R.
    • В Julia, Int[1, Int[2, 3]] не будет конкатенироваться, а вместо этого вызовет ошибку.
    • В Julia, Any[1, [2,3]] не будет конкатенироваться.
    • В Julia, Vector{Int}[[1, 2], [3, 4]] не будет конкатенироваться, но создаст объект, аналогичный списку списков в Python. Этот объект отличается от двумерного Array из Int.
  • В Julia для завершения блока требуется end. В отличие от Python, в Julia нет ключевого слова pass.
  • В Julia индексация массивов, строк и т. д. основана на 1, а не на 0.
  • Индексация срезов в Julia включает последний элемент, в отличие от Python. a[2:3] в Julia соответствует a[1:3] в Python.
  • В Julia не поддерживаются отрицательные индексы. В частности, последний элемент списка или массива индексируется с помощью end в Julia, а не -1, как в Python.
  • В Julia списки включений не поддерживают необязательную if-клаузу, которая есть в Python.
  • В Julia for, if, while, и т. д. блоки завершаются ключевым словом end. Уровень отступов не имеет значения, как в Python.
  • В Julia нет синтаксиса продолжения строки: если в конце строки введенное выражение является полным, то оно считается завершенным; в противном случае ввод продолжается. Один из способов принудительно продолжить выражение — заключить его в скобки.
  • Массивы Julia хранятся в порядке следования столбцов (порядке Fortran), тогда как массивы 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++.
  • Строковые литералы могут быть ограничены либо " или """, """ ограниченные литералы могут содержать " символы без кавычек, как в "\"" . Строковые литералы могут содержать значения других переменных или выражений, интерполированные в них, указанные $variablename или $(expression), которые оценивают имя переменной или выражение в контексте функции.
  • // обозначает Rational число, а не однострочный комментарий (который # в Julia)
  • #= обозначает начало многострочного комментария, а =# завершает его.
  • Функции в Julia возвращают значения из их последнего(их) выражения(ий) или ключевого слова return. От функций можно возвращать несколько значений, которые присваиваются как кортежи, например, (a, b) = myfunction() или a, b = myfunction(), вместо того, чтобы передавать указатели на значения, как это нужно в C/C++ (т. е. a = myfunction(&b)).
  • Julia не требует использования точек с запятой для завершения операторов. Результаты выражений не выводятся автоматически (за исключением интерактивного приглашения, т. е. REPL), и строки кода не должны заканчиваться точкой с запятой. println() или @printf() могут использоваться для вывода определенного вывода. В REPL ; можно использовать для подавления вывода. ; также имеет другое значение в [ ], что следует учитывать. ; могут использоваться для разделения выражений в одной строке, но они не строго необходимы во многих случаях и больше служат для повышения читаемости.
  • В Julia оператор $ выполняет побитовую операцию XOR, т. е. ^ в C/C++. Кроме того, побитовые операторы не имеют того же приоритета, что и в C/++, поэтому могут потребоваться скобки.
  • Оператор Julia ^ выполняет возведение в степень (pow), а не побитовое XOR, как в C/C++ (используйте $ в 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.5/manual/noteworthy-differences/

Spec-Zone.ru

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