Julia — гомоиконный функциональный язык программирования для технических расчётов. Несмотря на полную поддержку гомоиконных макросов, функций первого класса и конструкций управления низкого уровня, этот язык так же прост в изучении и применении, как и Python.
Документ описывает текущую dev-версию Julia от 18-о октября 2013 года.
1# Однострочные комментарии начинаются со знака решётки.
2
3####################################################
4## 1. Примитивные типы данных и операторы
5####################################################
6
7# Всё в Julia — выражение.
8
9# Простые численные типы
103 # => 3 (Int64)
113.2 # => 3.2 (Float64)
122 + 1im # => 2 + 1im (Complex{Int64})
132//3 # => 2//3 (Rational{Int64})
14
15# Доступны все привычные инфиксные операторы
161 + 1 # => 2
178 - 1 # => 7
1810 * 2 # => 20
1935 / 5 # => 7.0
205 / 2 # => 2.5 # деление Int на Int всегда возвращает Float
21div(5, 2) # => 2 # для округления к нулю используется div
225 \ 35 # => 7.0
232 ^ 2 # => 4 # возведение в степень
2412 % 10 # => 2
25
26# С помощью скобок можно изменить приоритет операций
27(1 + 3) * 2 # => 8
28
29# Побитовые операторы
30~2 # => -3 # НЕ (NOT)
313 & 5 # => 1 # И (AND)
322 | 4 # => 6 # ИЛИ (OR)
332 $ 4 # => 6 # сложение по модулю 2 (XOR)
342 >>> 1 # => 1 # логический сдвиг вправо
352 >> 1 # => 1 # арифметический сдвиг вправо
362 << 1 # => 4 # логический/арифметический сдвиг влево
37
38# Функция bits возвращает бинарное представление числа
39bits(12345)
40# => "0000000000000000000000000000000000000000000000000011000000111001"
41bits(12345.0)
42# => "0100000011001000000111001000000000000000000000000000000000000000"
43
44# Логические значения являются примитивами
45true
46false
47
48# Булевы операторы
49!true # => false
50!false # => true
511 == 1 # => true
522 == 1 # => false
531 != 1 # => false
542 != 1 # => true
551 < 10 # => true
561 > 10 # => false
572 <= 2 # => true
582 >= 2 # => true
59# Сравнения можно объединять цепочкой
601 < 2 < 3 # => true
612 < 3 < 2 # => false
62
63# Строки объявляются с помощью двойных кавычек — "
64"This is a string."
65
66# Символьные литералы создаются с помощью одинарных кавычек — '
67'a'
68
69# Строки индексируются как массивы символов
70"This is a string"[1] # => 'T' # Индексы начинаются с единицы
71# Индексирование не всегда правильно работает для UTF8-строк,
72# поэтому рекомендуется использовать итерирование (map, for-циклы и т.п.).
73
74# Для строковой интерполяции используется знак доллара ($):
75"2 + 2 = $(2 + 2)" # => "2 + 2 = 4"
76# В скобках можно использовать любое выражение языка.
77
78# Другой способ форматирования строк — макрос printf
79@printf "%d is less than %f" 4.5 5.3 # 5 is less than 5.300000
80
81####################################################
82## 2. Переменные и коллекции
83####################################################
84
85# Вывод
86println("I'm Julia. Nice to meet you!")
87
88# Переменные инициализируются без предварительного объявления
89some_var = 5 # => 5
90some_var # => 5
91
92# Попытка доступа к переменной до инициализации вызывает ошибку
93try
94 some_other_var # => ERROR: some_other_var not defined
95catch e
96 println(e)
97end
98
99# Имена переменных начинаются с букв.
100# После первого символа можно использовать буквы, цифры,
101# символы подчёркивания и восклицательные знаки.
102SomeOtherVar123! = 6 # => 6
103
104# Допустимо использование unicode-символов
105☃ = 8 # => 8
106# Это особенно удобно для математических обозначений
1072 * π # => 6.283185307179586
108
109# Рекомендации по именованию:
110# * имена переменных в нижнем регистре, слова разделяются символом
111# подчёркивания ('\_');
112#
113# * для имён типов используется CamelCase;
114#
115# * имена функций и макросов в нижнем регистре
116# без разделения слов символом подчёркивания;
117#
118# * имя функции, изменяющей переданные ей аргументы (in-place function),
119# оканчивается восклицательным знаком.
120
121# Массив хранит последовательность значений, индексируемых с единицы до n:
122a = Int64[] # => пустой массив Int64-элементов
123
124# Одномерный массив объявляется разделёнными запятой значениями.
125b = [4, 5, 6] # => массив из трёх Int64-элементов: [4, 5, 6]
126b[1] # => 4
127b[end] # => 6
128
129# Строки двумерного массива разделяются точкой с запятой.
130# Элементы строк разделяются пробелами.
131matrix = [1 2; 3 4] # => 2x2 Int64 Array: [1 2; 3 4]
132
133# push! и append! добавляют в список новые элементы
134push!(a,1) # => [1]
135push!(a,2) # => [1,2]
136push!(a,4) # => [1,2,4]
137push!(a,3) # => [1,2,4,3]
138append!(a,b) # => [1,2,4,3,4,5,6]
139
140# pop! удаляет из списка последний элемент
141pop!(b) # => возвращает 6; массив b снова равен [4,5]
142
143# Вернём 6 обратно
144push!(b,6) # b снова [4,5,6].
145
146a[1] # => 1 # индексы начинаются с единицы!
147
148# Последний элемент можно получить с помощью end
149a[end] # => 6
150
151# Операции сдвига
152shift!(a) # => 1 and a is now [2,4,3,4,5,6]
153unshift!(a,7) # => [7,2,4,3,4,5,6]
154
155# Восклицательный знак на конце названия функции означает,
156# что функция изменяет переданные ей аргументы.
157arr = [5,4,6] # => массив из 3 Int64-элементов: [5,4,6]
158sort(arr) # => [4,5,6]; но arr равен [5,4,6]
159sort!(arr) # => [4,5,6]; а теперь arr — [4,5,6]
160
161# Попытка доступа за пределами массива выбрасывает BoundsError
162try
163 a[0] # => ERROR: BoundsError() in getindex at array.jl:270
164 a[end+1] # => ERROR: BoundsError() in getindex at array.jl:270
165catch e
166 println(e)
167end
168
169# Вывод ошибок содержит строку и файл, где произошла ошибка,
170# даже если это случилось в стандартной библиотеке.
171# Если вы собрали Julia из исходных кодов,
172# то найти эти файлы можно в директории base.
173
174# Создавать массивы можно из последовательности
175a = [1:5] # => массив из 5 Int64-элементов: [1,2,3,4,5]
176
177# Срезы
178a[1:3] # => [1, 2, 3]
179a[2:] # => [2, 3, 4, 5]
180a[2:end] # => [2, 3, 4, 5]
181
182# splice! удаляет элемент из массива
183# Remove elements from an array by index with splice!
184arr = [3,4,5]
185splice!(arr,2) # => 4 ; arr теперь равен [3,5]
186
187# append! объединяет списки
188b = [1,2,3]
189append!(a,b) # теперь a равен [1, 2, 3, 4, 5, 1, 2, 3]
190
191# Проверка на вхождение
192in(1, a) # => true
193
194# Длина списка
195length(a) # => 8
196
197# Кортеж — неизменяемая структура.
198tup = (1, 2, 3) # => (1,2,3) # кортеж (Int64,Int64,Int64).
199tup[1] # => 1
200try:
201 tup[1] = 3 # => ERROR: no method setindex!((Int64,Int64,Int64),Int64,Int64)
202catch e
203 println(e)
204end
205
206# Многие функции над списками работают и для кортежей
207length(tup) # => 3
208tup[1:2] # => (1,2)
209in(2, tup) # => true
210
211# Кортежи можно распаковывать в переменные
212a, b, c = (1, 2, 3) # => (1,2,3) # a = 1, b = 2 и c = 3
213
214# Скобки из предыдущего примера можно опустить
215d, e, f = 4, 5, 6 # => (4,5,6)
216
217# Кортеж из одного элемента не равен значению этого элемента
218(1,) == 1 # => false
219(1) == 1 # => true
220
221# Обмен значений
222e, d = d, e # => (5,4) # d = 5, e = 4
223
224
225# Словари содержат ассоциативные массивы
226empty_dict = Dict() # => Dict{Any,Any}()
227
228# Для создания словаря можно использовать литерал
229filled_dict = ["one"=> 1, "two"=> 2, "three"=> 3]
230# => Dict{ASCIIString,Int64}
231
232# Значения ищутся по ключу с помощью оператора []
233filled_dict["one"] # => 1
234
235# Получить все ключи
236keys(filled_dict)
237# => KeyIterator{Dict{ASCIIString,Int64}}(["three"=>3,"one"=>1,"two"=>2])
238# Заметьте, словарь не запоминает порядок, в котором добавляются ключи.
239
240# Получить все значения.
241values(filled_dict)
242# => ValueIterator{Dict{ASCIIString,Int64}}(["three"=>3,"one"=>1,"two"=>2])
243# То же касается и порядка значений.
244
245# Проверка вхождения ключа в словарь
246in(("one", 1), filled_dict) # => true
247in(("two", 3), filled_dict) # => false
248haskey(filled_dict, "one") # => true
249haskey(filled_dict, 1) # => false
250
251# Попытка обратиться к несуществующему ключу выбросит ошибку
252try
253 filled_dict["four"] # => ERROR: key not found: four in getindex at dict.jl:489
254catch e
255 println(e)
256end
257
258# Используйте метод get со значением по умолчанию, чтобы избежать этой ошибки
259# get(dictionary,key,default_value)
260get(filled_dict,"one",4) # => 1
261get(filled_dict,"four",4) # => 4
262
263# Для коллекций неотсортированных уникальных элементов используйте Set
264empty_set = Set() # => Set{Any}()
265# Инициализация множества
266filled_set = Set(1,2,2,3,4) # => Set{Int64}(1,2,3,4)
267
268# Добавление элементов
269push!(filled_set,5) # => Set{Int64}(5,4,2,3,1)
270
271# Проверка вхождения элементов во множество
272in(2, filled_set) # => true
273in(10, filled_set) # => false
274
275# Функции для получения пересечения, объединения и разницы.
276other_set = Set(3, 4, 5, 6) # => Set{Int64}(6,4,5,3)
277intersect(filled_set, other_set) # => Set{Int64}(3,4,5)
278union(filled_set, other_set) # => Set{Int64}(1,2,3,4,5,6)
279setdiff(Set(1,2,3,4),Set(2,3,5)) # => Set{Int64}(1,4)
280
281
282####################################################
283## 3. Поток управления
284####################################################
285
286# Создадим переменную
287some_var = 5
288
289# Выражение if. Отступы не имеют значения.
290if some_var > 10
291 println("some_var is totally bigger than 10.")
292elseif some_var < 10 # Необязательная ветка elseif.
293 println("some_var is smaller than 10.")
294else # else-ветка также опциональна.
295 println("some_var is indeed 10.")
296end
297# => prints "some var is smaller than 10"
298
299
300# Цикл for проходит по итерируемым объектам
301# Примеры итерируемых типов: Range, Array, Set, Dict и String.
302for animal=["dog", "cat", "mouse"]
303 println("$animal is a mammal")
304 # Для вставки значения переменной или выражения в строку используется $
305end
306# Выведет:
307# dog is a mammal
308# cat is a mammal
309# mouse is a mammal
310
311# Другой вариант записи.
312for animal in ["dog", "cat", "mouse"]
313 println("$animal is a mammal")
314end
315# Выведет:
316# dog is a mammal
317# cat is a mammal
318# mouse is a mammal
319
320for a in ["dog"=>"mammal","cat"=>"mammal","mouse"=>"mammal"]
321 println("$(a[1]) is a $(a[2])")
322end
323# Выведет:
324# dog is a mammal
325# cat is a mammal
326# mouse is a mammal
327
328for (k,v) in ["dog"=>"mammal","cat"=>"mammal","mouse"=>"mammal"]
329 println("$k is a $v")
330end
331# Выведет:
332# dog is a mammal
333# cat is a mammal
334# mouse is a mammal
335
336# Цикл while выполняется до тех пор, пока верно условие
337x = 0
338while x < 4
339 println(x)
340 x += 1 # Короткая запись x = x + 1
341end
342# Выведет:
343# 0
344# 1
345# 2
346# 3
347
348# Обработка исключений
349try
350 error("help")
351catch e
352 println("caught it $e")
353end
354# => caught it ErrorException("help")
355
356
357####################################################
358## 4. Функции
359####################################################
360
361# Для определения новой функции используется ключевое слово 'function'
362#function имя(аргументы)
363# тело...
364#end
365function add(x, y)
366 println("x is $x and y is $y")
367
368 # Функция возвращает значение последнего выражения
369 x + y
370end
371
372add(5, 6) # => Вернёт 11, напечатав "x is 5 and y is 6"
373
374# Функция может принимать переменное количество позиционных аргументов.
375function varargs(args...)
376 return args
377 # для возвращения из функции в любом месте используется 'return'
378end
379# => varargs (generic function with 1 method)
380
381varargs(1,2,3) # => (1,2,3)
382
383# Многоточие (...) — это splat.
384# Мы только что воспользовались им в определении функции.
385# Также его можно использовать при вызове функции,
386# где он преобразует содержимое массива или кортежа в список аргументов.
387Set([1,2,3]) # => Set{Array{Int64,1}}([1,2,3]) # формирует множество массивов
388Set([1,2,3]...) # => Set{Int64}(1,2,3) # эквивалентно Set(1,2,3)
389
390x = (1,2,3) # => (1,2,3)
391Set(x) # => Set{(Int64,Int64,Int64)}((1,2,3)) # множество кортежей
392Set(x...) # => Set{Int64}(2,3,1)
393
394
395# Опциональные позиционные аргументы
396function defaults(a,b,x=5,y=6)
397 return "$a $b and $x $y"
398end
399
400defaults('h','g') # => "h g and 5 6"
401defaults('h','g','j') # => "h g and j 6"
402defaults('h','g','j','k') # => "h g and j k"
403try
404 defaults('h') # => ERROR: no method defaults(Char,)
405 defaults() # => ERROR: no methods defaults()
406catch e
407 println(e)
408end
409
410# Именованные аргументы
411function keyword_args(;k1=4,name2="hello") # обратите внимание на ;
412 return ["k1"=>k1,"name2"=>name2]
413end
414
415keyword_args(name2="ness") # => ["name2"=>"ness","k1"=>4]
416keyword_args(k1="mine") # => ["k1"=>"mine","name2"=>"hello"]
417keyword_args() # => ["name2"=>"hello","k2"=>4]
418
419# В одной функции можно совмещать все виды аргументов
420function all_the_args(normal_arg, optional_positional_arg=2; keyword_arg="foo")
421 println("normal arg: $normal_arg")
422 println("optional arg: $optional_positional_arg")
423 println("keyword arg: $keyword_arg")
424end
425
426all_the_args(1, 3, keyword_arg=4)
427# Выведет:
428# normal arg: 1
429# optional arg: 3
430# keyword arg: 4
431
432# Функции в Julia первого класса
433function create_adder(x)
434 adder = function (y)
435 return x + y
436 end
437 return adder
438end
439
440# Анонимная функция
441(x -> x > 2)(3) # => true
442
443# Эта функция идентичная предыдущей версии create_adder
444function create_adder(x)
445 y -> x + y
446end
447
448# Если есть желание, можно воспользоваться полным вариантом
449function create_adder(x)
450 function adder(y)
451 x + y
452 end
453 adder
454end
455
456add_10 = create_adder(10)
457add_10(3) # => 13
458
459
460# Встроенные функции высшего порядка
461map(add_10, [1,2,3]) # => [11, 12, 13]
462filter(x -> x > 5, [3, 4, 5, 6, 7]) # => [6, 7]
463
464# Списковые сборки
465[add_10(i) for i=[1, 2, 3]] # => [11, 12, 13]
466[add_10(i) for i in [1, 2, 3]] # => [11, 12, 13]
467
468####################################################
469## 5. Типы
470####################################################
471
472# Julia has a type system.
473# Каждое значение имеет тип, но переменные не определяют тип значения.
474# Функция `typeof` возвращает тип значения.
475typeof(5) # => Int64
476
477# Types are first-class values
478# Типы являются значениями первого класса
479typeof(Int64) # => DataType
480typeof(DataType) # => DataType
481# Тип DataType представляет типы, включая себя самого.
482
483# Типы используются в качестве документации, для оптимизации и организации.
484# Статически типы не проверяются.
485
486# Пользователь может определять свои типы
487# Типы похожи на структуры в других языках
488# Новые типы определяются с помощью ключевого слова `type`
489
490# type Name
491# field::OptionalType
492# ...
493# end
494type Tiger
495 taillength::Float64
496 coatcolor # отсутствие типа равносильно `::Any`
497end
498
499# Аргументы конструктора по умолчанию — свойства типа
500# в порядке их определения.
501tigger = Tiger(3.5,"orange") # => Tiger(3.5,"orange")
502
503# Тип объекта по сути является конструктором значений такого типа
504sherekhan = typeof(tigger)(5.6,"fire") # => Tiger(5.6,"fire")
505
506# Эти типы, похожие на структуры, называются конкретными.
507# Можно создавать объекты таких типов, но не их подтипы.
508# Другой вид типов — абстрактные типы.
509
510# abstract Name
511abstract Cat # просто имя и точка в иерархии типов
512
513# Объекты абстрактных типов создавать нельзя,
514# но зато от них можно наследовать подтипы.
515# Например, Number — это абстрактный тип.
516subtypes(Number) # => 6 элементов в массиве Array{Any,1}:
517 # Complex{Float16}
518 # Complex{Float32}
519 # Complex{Float64}
520 # Complex{T<:Real}
521 # ImaginaryUnit
522 # Real
523subtypes(Cat) # => пустой массив Array{Any,1}
524
525# У всех типов есть супертип. Для его определения есть функция `super`.
526typeof(5) # => Int64
527super(Int64) # => Signed
528super(Signed) # => Real
529super(Real) # => Number
530super(Number) # => Any
531super(super(Signed)) # => Number
532super(Any) # => Any
533# Все эти типы, за исключением Int64, абстрактные.
534
535# Для создания подтипа используется оператор <:
536type Lion <: Cat # Lion — это подтип Cat
537 mane_color
538 roar::String
539end
540
541# У типа может быть несколько конструкторов.
542# Для создания нового определите функцию с именем, как у типа,
543# и вызовите имеющийся конструктор.
544Lion(roar::String) = Lion("green",roar)
545# Мы создали внешний (т.к. он находится вне определения типа) конструктор.
546
547type Panther <: Cat # Panther — это тоже подтип Cat
548 eye_color
549
550 # Определим свой конструктор вместо конструктора по умолчанию
551 Panther() = new("green")
552end
553# Использование внутренних конструкторов позволяет
554# определять, как будут создаваться объекты типов.
555# Но по возможности стоит пользоваться внешними конструкторами.
556
557####################################################
558## 6. Мультиметоды
559####################################################
560
561# Все именованные функции являются generic-функциями,
562# т.е. все они состоят из разных методов.
563# Каждый конструктор типа Lion — это метод generic-функции Lion.
564
565# Приведём пример без использования конструкторов, создадим функцию meow
566
567# Определения Lion, Panther и Tiger
568function meow(animal::Lion)
569 animal.roar # доступ к свойству типа через точку
570end
571
572function meow(animal::Panther)
573 "grrr"
574end
575
576function meow(animal::Tiger)
577 "rawwwr"
578end
579
580# Проверка
581meow(tigger) # => "rawwr"
582meow(Lion("brown","ROAAR")) # => "ROAAR"
583meow(Panther()) # => "grrr"
584
585# Вспомним иерархию типов
586issubtype(Tiger,Cat) # => false
587issubtype(Lion,Cat) # => true
588issubtype(Panther,Cat) # => true
589
590# Определим функцию, принимающую на вход объекты типа Cat
591function pet_cat(cat::Cat)
592 println("The cat says $(meow(cat))")
593end
594
595pet_cat(Lion("42")) # => выведет "The cat says 42"
596try
597 pet_cat(tigger) # => ERROR: no method pet_cat(Tiger,)
598catch e
599 println(e)
600end
601
602# В объектно-ориентированных языках распространена одиночная диспетчеризация —
603# подходящий метод выбирается на основе типа первого аргумента.
604# В Julia все аргументы участвуют в выборе нужного метода.
605
606# Чтобы понять разницу, определим функцию с несколькими аргументами.
607function fight(t::Tiger,c::Cat)
608 println("The $(t.coatcolor) tiger wins!")
609end
610# => fight (generic function with 1 method)
611
612fight(tigger,Panther()) # => выведет The orange tiger wins!
613fight(tigger,Lion("ROAR")) # => выведет The orange tiger wins!
614
615# Переопределим поведение функции, если Cat-объект является Lion-объектом
616fight(t::Tiger,l::Lion) = println("The $(l.mane_color)-maned lion wins!")
617# => fight (generic function with 2 methods)
618
619fight(tigger,Panther()) # => выведет The orange tiger wins!
620fight(tigger,Lion("ROAR")) # => выведет The green-maned lion wins!
621
622# Драться можно не только с тиграми!
623fight(l::Lion,c::Cat) = println("The victorious cat says $(meow(c))")
624# => fight (generic function with 3 methods)
625
626fight(Lion("balooga!"),Panther()) # => выведет The victorious cat says grrr
627try
628 fight(Panther(),Lion("RAWR")) # => ERROR: no method fight(Panther,Lion)
629catch
630end
631
632# Вообще, пускай кошачьи могут первыми проявлять агрессию
633fight(c::Cat,l::Lion) = println("The cat beats the Lion")
634# => Warning: New definition
635# fight(Cat,Lion) at none:1
636# is ambiguous with
637# fight(Lion,Cat) at none:2.
638# Make sure
639# fight(Lion,Lion)
640# is defined first.
641#fight (generic function with 4 methods)
642
643# Предупреждение говорит, что неясно, какой из методов вызывать:
644fight(Lion("RAR"),Lion("brown","rarrr")) # => выведет The victorious cat says rarrr
645# Результат может оказаться разным в разных версиях Julia
646
647fight(l::Lion,l2::Lion) = println("The lions come to a tie")
648fight(Lion("RAR"),Lion("brown","rarrr")) # => выведет The lions come to a tie
649
650
651# Под капотом
652# Язык позволяет посмотреть на сгенерированные ассемблерный и LLVM-код.
653
654square_area(l) = l * l # square_area (generic function with 1 method)
655
656square_area(5) #25
657
658# Что происходит, когда мы передаём функции square_area целое число?
659code_native(square_area, (Int32,))
660 # .section __TEXT,__text,regular,pure_instructions
661 # Filename: none
662 # Source line: 1 # Вводная часть
663 # push RBP
664 # mov RBP, RSP
665 # Source line: 1
666 # movsxd RAX, EDI #
667 # imul RAX, RAX #
668 # pop RBP #
669 # ret #
670
671code_native(square_area, (Float32,))
672 # .section __TEXT,__text,regular,pure_instructions
673 # Filename: none
674 # Source line: 1
675 # push RBP
676 # mov RBP, RSP
677 # Source line: 1
678 # vmulss XMM0, XMM0, XMM0 # Произведение чисел одинарной точности (AVX)
679 # pop RBP
680 # ret
681
682code_native(square_area, (Float64,))
683 # .section __TEXT,__text,regular,pure_instructions
684 # Filename: none
685 # Source line: 1
686 # push RBP
687 # mov RBP, RSP
688 # Source line: 1
689 # vmulsd XMM0, XMM0, XMM0 # Произведение чисел двойной точности (AVX)
690 # pop RBP
691 # ret
692 #
693# Если хотя бы один из аргументов является числом с плавающей запятой,
694# то Julia будет использовать соответствующие инструкции.
695# Вычислим площать круга
696circle_area(r) = pi * r * r # circle_area (generic function with 1 method)
697circle_area(5) # 78.53981633974483
698
699code_native(circle_area, (Int32,))
700 # .section __TEXT,__text,regular,pure_instructions
701 # Filename: none
702 # Source line: 1
703 # push RBP
704 # mov RBP, RSP
705 # Source line: 1
706 # vcvtsi2sd XMM0, XMM0, EDI # Загрузить целое число (r)
707 # movabs RAX, 4593140240 # Загрузить pi
708 # vmulsd XMM1, XMM0, QWORD PTR [RAX] # pi * r
709 # vmulsd XMM0, XMM0, XMM1 # (pi * r) * r
710 # pop RBP
711 # ret
712 #
713
714code_native(circle_area, (Float64,))
715 # .section __TEXT,__text,regular,pure_instructions
716 # Filename: none
717 # Source line: 1
718 # push RBP
719 # mov RBP, RSP
720 # movabs RAX, 4593140496
721 # Source line: 1
722 # vmulsd XMM1, XMM0, QWORD PTR [RAX]
723 # vmulsd XMM0, XMM1, XMM0
724 # pop RBP
725 # ret
726 #
Что дальше? ¶
Для более подробной информации читайте документацию по языку
Если вам нужна помощь, задавайте вопросы в списке рассылки.