OCaml

OCaml
Изображение логотипа
Класс языка объектно-ориентированный, язык функционального программирования, мультипарадигмальный, императивный, диалект и свободное и открытое программное обеспечение
Появился в 1996
Автор Ксавье Лерой и Damien Doligez[вд]
Разработчик INRIA
Расширение файлов .ml или .mli
Выпуск
Испытал влияние SML
Лицензия публичная лицензия Q и LGPL-2.1[вд]
Сайт ocaml.org (англ.)
ОС Unix-подобная операционная система[2]
Логотип Викисклада Медиафайлы на Викискладе

OCaml (Objective Caml) — объектно-ориентированный язык функционального программирования общего назначения. Был разработан с учётом безопасности исполнения и надёжности программ. Поддерживает функциональную, императивную и объектно-ориентированную парадигмы программирования. Самый распространённый в практической работе диалект языка ML.

Появился в 1996 году под названием Objective Caml, когда Дидье Реми (Didier Rémy) и Жером Вуйон (Jérôme Vouillon) реализовали поддержку объектно-ориентированного программирования для языка Caml, первоначально разработанного во французском институте INRIA. Официально переименован в OCaml в 2011 году[3].

Инструментарий OCaml включает в себя интерпретатор, компилятор в байткод и оптимизирующий компилятор в машинный код, сравнимый по эффективности с Java и лишь немного уступающий по быстродействию C и C++[4].

На языке, в частности, написан рендеринг формул Википедии, использующих тег <math>, файлообменный клиент MLDonkey, стек управления гипервизором Xen xapi (является частью Xen Server/Xen Cloud Platform), язык программирования Haxe.

Роль в информатике

Является языком программирования общего назначения, но при этом имеет свои сложившиеся области применения[5].

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

Другой областью успешного применения OCaml являются приложения, управляемые данными (data-driven). К этой области относится обработка текста, а также написание компиляторов. OCaml имеет не только средства для текстовой обработки (какими славится, например, Perl или AWK), но и инструменты для глубокого семантического анализа и преобразования текста, что делает OCaml применимым в задачах интеллектуального анализа данных (англ. data mining)[5].

OCaml, как и другие диалекты ML, используются в исследовательских задачах и задачах верификации, при котором основной код пишется на некотором языке программирования, а затем формально верифицируется и анализируется программой на OCaml[5]. Например, на OCaml написана система интерактивного доказательства теорем Coq.

Занимает особое место среди языков программирования благодаря сочетанию эффективности, выразительности и практичности. Среди особенностей языка, развивавшихся в течение более чем 40 лет, со времени создания ML, выделяют следующие[6]:

История

OCaml ведёт своё происхождение от ML (англ. meta language), который был реализован на диалекте Лиспа Робином Милнером в 1972 году в качестве программного средства для доказательства теорем, как метаязык логики вычислимых функций (LCF, англ. logic for computable functions). Позднее был сделан компилятор, а к 1980 году ML стал полноценной системой программирования[7].

Ги Кузино (Guy Cousineau) добавил в язык алгебраические типы данных и сопоставление с образцом и определил ML в виде категориальной абстрактной машины (CAM). Таким образом, CAM-ML мог быть описан, верифицирован и оптимизирован, что явилось шагом вперёд для ML[8].

Дальнейшим развитием был созданный к 1987 году Аскандером Суарецом (Ascánder Suárez) и продолженный Пьером Вейсом (Pierre Weis) и Мичелом Мони (Michel Mauny) язык Caml (переигранное CAM-ML)[7][8].

В 1990 году Ксавье Лерой (Xavier Leroy) и Дамьен Долигез (Damien Doligez) выпустили новую реализацию, названную Caml Light. В этой реализации на Си использовался интерпретатор байт-кода и быстрый сборщик мусора. С написанием библиотек язык стал использоваться в образовании и исследовательских институтах[7][8].

В 1995 году увидел свет Caml Special Light, развиваемый К. Лероем. Система программирования получила компилятор в машинные коды, что поставило эффективность исполняемого кода в один ряд с другими компилируемыми языками. В то же время была разработана система модулей, идея которой была заимствована из Standard ML[7].

В современном виде OCaml появился в 1996 году, когда Дидье Реми (Didier Rémy) и Джером Вуйон (Jérôme Vouillon) реализовали для языка стройную и эффективную поддержку объектов. Эта объектная система позволяет на этапе компиляции в типобезопасной манере использовать идиомы объектно-ориентированного программирования, без свойственных C++ и Java проверок времени выполнения[7].

В 2000-х годах язык плавно развивался, одновременно получая всё большее признание в коммерческих проектах и образовании. Среди разработанного в это время можно отметить полиморфные методы и вариантные типы, именованные и необязательные параметры, модули первого класса, обобщённые алгебраические типы данных (GADT). Язык стал поддерживать несколько аппаратных платформ (X86, ARM, SPARC, PowerPC)[7][8].

Базовая семантика

Модель вычислений OCaml как языка функционального программирования строится на трёх основных конструкциях лямбда-исчисления: переменных, определениях функций и применении функции к аргументам[9].

Переменные

Переменная — идентификатор, значение которого связано с определённой величиной. Имена переменных начинаются со строчной буквы или подчёркивания. Привязка обычно выполняется с помощью ключевого слова let, как в следующем примере в интерактивной оболочке[10]:

let v = 1 ;;

Переменные имеют область видимости. Например, в интерактивной оболочке переменную можно использовать в следующих за её привязкой командах. Аналогично, переменную, определённую в модуле, можно использовать после определения в данном модуле[10].

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

# let area radius =
      let pi = 3.14 in
      radius *. radius *. pi ;;
val area : float -> float = <fun>
# area 2.0 ;;
- : float = 12.56

В OCaml привязки переменных являются неизменяемыми (как в математических уравнениях), то есть, значение переменной «присваивается» только один раз (единичное присваивание). Другое дело, что внутри let-in может быть другой let-in, в котором вводится другая переменная, которая может «затенить» первую[10].

Функции

Для определения функций в OCaml есть несколько синтаксических конструкций.

Функции можно определить с помощью ключевого слова function. Выражение для функции выглядит следующим образом[11]:

function x -> x + 1

В данном случае функция анонимная, и её можно использовать в качестве параметров других функций или применить к некоторому аргументу, например:

(function x -> x + 1) 5

Типом этой функции является int -> int, то есть, функция принимает целое и возвращает целое.

Функция может иметь несколько аргументов[12]:

function (x, y) -> x - y

В этом примере её тип: int * int -> int, то есть, на входе функции — пара, а на выходе — целое.

Есть и другой подход представления функций нескольких аргументов — преобразование N-арной функции в N функций одного аргумента — каррирование. Следующие два вида записи функции, вычисляющей произведение целочисленных аргументов, эквивалентны[12]:

function x -> function y -> x * y
fun x y -> x * y

Именованные функции можно получить, связав переменную с функцией[11]. Определение именованной функции настолько частая операция, что имеет отдельную синтаксическую поддержку. Следующие три записи — эквивалентные способы определить функцию (в интерактивной оболочке):

# let prod = function x -> function y -> x * y ;;
val prod : int -> int -> int = <fun>
# let prod x y = x * y ;;
val prod : int -> int -> int = <fun>
# let prod = fun x y -> x * y ;;
val prod : int -> int -> int = <fun>

Функции двух аргументов можно определить для использования инфиксной записи[11]:

# let (^^) x y = x**2.0 +. y**2.0 ;;
val ( ^^ ) : float -> float -> float = <fun>
# 2.0 ^^ 3.0 ;;
- : float = 13.
# (^^) 2.0 3.0 ;;
- : float = 13.

В этом примере определена функция (^^), вычисляющая сумму квадратов двух чисел с плавающей запятой. Последние два вида записи эквивалентны.

Рекурсивные функции, то есть функции, ссылающиеся на своё же определение, можно задать с помощью let rec[11]:

# let rec fac n =
    match n with 
    | 0 -> 1
    | x -> x * fac (x - 1)
  ;;

В этом же примере вычисления факториала применено сопоставление с образцом (конструкция match-with).

Аргументы функции можно определить как именованные. Именованные аргументы можно указывать в любом порядке[11]:

# let divmod ~x ~y = (x / y, x mod y) ;;
val divmod : x:int -> y:int -> int * int = <fun>
# divmod ~x:4 ~y:3 ;;
- : int * int = (1, 1)
# divmod ~y:3 ~x:4 ;;
- : int * int = (1, 1)

В OCaml можно опускать значения, используя уплотнённую запись (англ. label punning), если имя параметра и переменной совпадают[11]:

# let x = 4 in
  let y = 3 in
  divmod ~x ~y ;;
- : int * int = (1, 1)

Выражения

Ассоциативность операций в выражениях OCaml определяется префиксом, распространяясь таким образом на операции, определённые пользователем. Знак - работает и как префиксная, и как инфиксная операция, причём при необходимости использовать в качестве префикса совместно с применением функции параметр нужно заключить в скобки[13].

Префикс операции Ассоциативность
! ? ~ Префикс
. .( .[ .{
применение функции, конструктора, метки, assert, lazy Левая
- -. Префикс
** lsl lsr asr Правая
* / % mod land lor lxor Левая
+ - Левая
:: Правая
@ ^ Правая
& $ != Левая
& && Правая
or || Правая
,
<- := Правая
if
; Правая
let match fun function try

Система типов

Примитивные типы

Язык OCaml имеет несколько примитивных типов: числовые типы (целый и числа с плавающей запятой), символьный, строки символов, булевый[14].

Целый тип представляет целые числа из интервала [−230, 230 − 1] и [−262, 262 − 1] для 32- и 64-битных архитектур соответственно. С целыми числами можно производить обычные операции сложения, вычитания, умножения, деления, взятия остатка от деления: +, -, *, /, mod. В случае выхода результата за допустимый интервал ошибки не происходит, а результат вычисляется по модулю границы интервала[15].

Числа с плавающей запятой представляются 53-битной мантиссой и порядком из интервала [−1022, 1023], следуя стандарту IEEE 754 для чисел с двойной точностью. В операциях эти числа нельзя смешивать с целыми. Кроме того, операции над числами с плавающей запятой синтаксически отличаются от целочисленных операций: +., -., *., /.. Также имеется операция возведения в степень: **. Для преобразования целых чисел в числа с плавающей запятой и обратно доступны функции: float_of_int и int_of_float[15].

Для чисел с плавающей запятой имеются и другие математические функции: тригонометрические (sin, cos, tan, asin, acos, atan), округления (ceil, floor), экспоненциальная (exp), логарифмические (log, log10), а также извлечение квадратного корня (sqrt)[15]. Для числовых типов имеются и полиморфные операции сравнения[15].

Символьный тип — char — соответствует представлению символа с кодом от 0 до 255 (первые 128 символов совпадают с ASCII). Строчный тип — string — последовательность символов (максимальная длина: 224 — 6)[16]. Пример с использованием функции преобразования целого к строке и операции конкатенации:

# "Example " ^ string_of_int(2) ;;
- : string = "Example 2"

Булевый тип имеет два значения: true (истина) и false (ложь). Операции над величинами булевого типа: унарная not (отрицание), бинарные: && (и), || (или). Бинарные операции вычисляют сначала левый аргумент, а правый — только если требуется[17].

Булевые значения получаются в результате сравнений: = (структурное равенство), == (тождество), <> (отрицание структурного равенства), != (отрицание тождества), <, >, <=, >=. Для примитивных типов кроме строк и чисел с плавающей точкой структурное равенство и тождество совпадают, для других типов тождественными считаются значения, располагающиеся по одному адресу в памяти, а при структурном сравнении значения проверяются покомпонентно[17].

Кроме того, в OCaml имеется специальный тип unit, который имеет всего одно значение — ()[17].

Списки

В OCaml список — конечная неизменяемая последовательность элементов одного типа, реализованная как односвязный список. Следующий пример демонстрирует синтаксис списка[18]:

# ['a'; 'b'; 'c'] ;;
- : char list = ['a'; 'b'; 'c']
# 'a' :: ('b' :: ('c' :: [])) ;;
- : char list = ['a'; 'b'; 'c']
# 'a' :: 'b' :: 'c' :: [] ;;
- : char list = ['a'; 'b'; 'c']
# [] ;;
- : 'a list = []

Операция :: позволяет построить список на основе нового элемента и хвоста старого списка. При этом «старый» список не изменяется:

# let lst = [1; 2] ;;
val lst : int list = [1; 2]
# let lst1 = 0 :: lst ;;
val lst1 : int list = [0; 1; 2]
# lst ;;
- : int list = [1; 2]
# lst1 ;;
- : int list = [0; 1; 2]
Пример: вычисление суммы элементов списка

Список является одним из основных типов данных в OCaml. Следующий пример кода определяет рекурсивную (обратите внимание на ключевое слово rec) функцию, которая перебирает элементы данного списка и возвращает их сумму:

let rec sum xs =
  match xs with
    | []       -> 0
    | x :: xs' -> x + sum xs'
 # sum [1;2;3;4;5];;
 - : int = 15

Другой способ подсчёта суммы заключается в использовании функции свёртки:

let sum xs =
    List.fold_left (+) 0 xs

  # sum [1;2;3;4;5];;
  - : int = 15

Записи

Записи являются важным элементом в системе типов OCaml. Запись представляет собой набор хранимых вместе значений, при котором каждый элемент значения-записи доступен по своему имени — имени поля записи. Пример описания типа, связывания записи с переменной и доступ к полю записи[19]:

# type user =
    { login       : string;
      password    : string;
      nick        : string;
    };;
# let usr = { login = "myuser"; password = "secret"; nick = "aka" ; } ;;
val usr : user = {login = "myuser"; password = "secret"; nick = "aka"}
# usr.nick ;;
- : string = "aka"

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

Как и в случае с другими типами, тип может быть параметризован. Другие возможности записей[19]:

  • сопоставление с образцом (irrefutable)
  • синтаксические уплотнение полей (field punning) записи в случае совпадения имён полей и переменных
  • повторное использование полей и разрешение неоднозначности с помощью модулей
  • функциональное обновление (functional update) записи
  • изменяемые (mutable) поля
  • fieldslib и поле записи как объект первого класса
  • итераторы полей

Вариантный тип

Вариантный тип представляет данные, которые могут принимать различные формы, определяемые явно заданными метками. В следующем примере определён тип для базовых цветов[20]:

# type main_color = Red | Green | Blue ;;
# Blue ;; 
- : main_color = Blue
# (Red, Blue) ;;
- : main_color * main_color = (Red, Blue)

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

# type color_scheme = RGB of int * int * int | CMYK of float * float * float * float;;
type color_scheme =
    RGB of int * int * int
  | CMYK of float * float * float * float

При определении функций вариантный тип естественно сочетается с сопоставлением с образцом.

Объекты

В OCaml объекты и их типы полностью отделены от системы классов. Классы используются для построения объектов и поддержки наследования, но не являются типами объектов. Объекты имеют собственные объектные типы (object types), и для работы с объектами классы применять необязательно. Объекты не так часто используются в OCaml (так, система модулей является более выразительной, чем объекты, так как модули могут включать типы, а классы и объекты — нет). Основным преимуществом объектов перед записями — они не требуют объявления типов и обладают большей гибкостью благодаря полиморфизму строчных переменных (англ. row polymorphism). С другой стороны, преимущества объектов проявляются при использовании системы классов. В отличие от модулей, классы поддерживают позднее связывание, что позволяет ссылаться на методы объекта без статически заданной реализации и использовать открытую рекурсию (в случае с модулями можно использовать функции и функторы, но синтаксически такие описания требуют написания большего количества кода)[21].

Вывод типов

Хотя OCaml является языком программирования с сильной типизацией, система вывода типов (англ. type inference) позволяет определять тип выражения на основе имеющейся информации о его компонентах. В следующем примере функции проверки числа на чётность не указано ни одной декларации типа, и тем не менее у компилятора языка есть полная информация о типе функции[22]:

# let odd x = x mod 2 <> 0 ;;
val odd : int -> bool = <fun>

Императивное программирование и функции с побочными эффектами

Помимо функциональных, язык содержит средства императивного программирования: функции с побочными эффектами, изменяемые (mutable) данные, императивные синтаксические конструкции, в частности, явные циклы while и for[23].

Следующий пример напечатает на стандартном выводе (это — побочный эффект функции printf) 11 строк:

for i = 0 to 10 do 
  Printf.printf "i =%d\n" i
done;;

В следующем (довольно искусственном) примере элементы массива на месте увеличиваются на единицу в цикле с предусловием. Для индекса массива используется ссылка (ref), которая инкрементируется в теле цикла:

# let incr_ar ar =
    let i = ref 0 in
    while !i < Array.length ar do
      ar.(!i) <- ar.(!i) + 1;
      incr i
  done ;;
val incr_ar : int array -> unit = <fun>
# let nums = [|1;2;3;4;5|];;
val nums : int array = [|1; 2; 3; 4; 5|]
# incr_ar nums;;
- : unit = ()
# nums;;
- : int array = [|2; 3; 4; 5; 6|]

Побочные эффекты позволяют оптимизировать вычисления, в особенности, когда речь идёт о значительных преобразованиях на больших массивах данных. Также с их помощью реализуются ленивые вычисления и мемоизация[23].

Крупномасштабное программирование

Модульность

OCaml можно представить себе как состоящий из двух языков: язык ядра со значениями и типами и язык модулей и их сигнатур. Эти языки образуют два слоя в том смысле, что модули могут содержать типы и значения, а обычные значения не могут содержать модулей и модулей-типов. Тем не менее, OCaml предлагает механизм модулей первого класса, которые могут быть значениями и при необходимости преобразуются в обычные модули и обратно[24].

Функторы

Система модулей OCaml не ограничивается модульной организацией кода и интерфейсами. Одними из важных инструментов обобщённого программирования являются функторы. Упрощённо говоря, функторы являются функцией из модуля в модули, что позволяет реализовать следующие механизмы[25]:

Примеры программ

Запуск интерпретатора OCaml

Для запуска интерпретатора языка OCaml необходимо в консоли ввести следующую команду:

$ ocaml
       OCaml version 4.08.1
#

Вычисления можно производить в интерактивном режиме, например:

# 1 + 2 * 3;;
- : int = 7

Hello world

Следующая программа «hello.ml»:

print_endline "Hello World!";;

может быть скомпилирована либо в байт-код:

$ ocamlc hello.ml -o hello

либо в оптимизированный машинный код:

$ ocamlopt hello.ml -o hello

и запущена:

$ ./hello
Hello World!
$

Быстрая сортировка

В следующем примере приведён алгоритм быстрой сортировки, который сортирует список в порядке возрастания:

let rec qsort = function
   | [] -> []
   | pivot :: rest ->
       let is_less x = x < pivot in
       let left, right = List.partition is_less rest in
       qsort left @ [pivot] @ qsort right

Последовательность Фибоначчи

let rec fib_aux n a b =
  match n with
  | 0 -> a
  | _ -> fib_aux (n - 1) (a + b) a
let fib n = fib_aux n 0 1

См. также

Примечания

  1. OCaml 5.2.1 Release Notes
  2. https://ocaml.org/docs/up-and-running
  3. A History of OCaml. Дата обращения: 22 апреля 2019. Архивировано 1 сентября 2015 года.
  4. Minsky, 2011.
  5. 1 2 3 4 Smith, 2006, p. 2—3.
  6. Minsky, Madhavapeddy, Hickey, 2013, Why OCaml?.
  7. 1 2 3 4 5 6 Minsky, Madhavapeddy, Hickey, 2013, A Brief History.
  8. 1 2 3 4 Smith, 2006, p. 3—4.
  9. Chailloux, Manoury, Pagano — Developing with OCaml, 2007, p. 11—12.
  10. 1 2 3 Minsky, Madhavapeddy, Hickey, 2013, Variables.
  11. 1 2 3 4 5 6 Minsky, Madhavapeddy, Hickey, 2013, Functions.
  12. 1 2 Chailloux, Manoury, Pagano — Developing with OCaml, 2007, p. 23.
  13. OCaml manual: 6.7 Expressions. Дата обращения: 6 января 2015. Архивировано 1 января 2015 года.
  14. Chailloux, Manoury, Pagano — Developing with OCaml, 2007, p. 12.
  15. 1 2 3 4 Chailloux, Manoury, Pagano — Developing with OCaml, 2007, p. 13.
  16. Chailloux, Manoury, Pagano — Developing with OCaml, 2007, p. 15.
  17. 1 2 3 Chailloux, Manoury, Pagano — Developing with OCaml, 2007, p. 15—16.
  18. Minsky, Madhavapeddy, Hickey, 2013, List Basics.
  19. 1 2 Minsky, Madhavapeddy, Hickey, 2013, Chapter 5. Records.
  20. Minsky, Madhavapeddy, Hickey, 2013, Chapter 6. Variants.
  21. Minsky, Madhavapeddy, Hickey, 2013, Objects.
  22. Minsky, Madhavapeddy, Hickey, 2013, Functions and Type Inference.
  23. 1 2 Minsky, Madhavapeddy, Hickey, 2013, Imperative Programming.
  24. Minsky, Madhavapeddy, Hickey, 2013, First-Class Modules.
  25. Minsky, Madhavapeddy, Hickey, 2013, Functors.

Литература

Список книг, доступных онлайн

  • Minsky, Y. and Madhavapeddy, A. and Hickey, J. Real World OCaml: Functional Programming for the Masses. — O'Reilly Media, 2013. — 510 p. — ISBN 9781449324766.
    • Перевод на русский язык: Мински, Ярон; Мадхавапедди, Анил; Хикки, Джейсон. Программирование на языке OCaml = Real World OCaml: Functional Programming for the Masses. — ДМК, 2014. — 536 с. — (Функциональное программирование). — ISBN 978-5-97060-102-0.

Ссылки


Read other articles:

農業技術者・政治家の「丹下乾三」とは別人です。 丹下健三生誕1913年(大正2年)9月4日大阪府堺市死没 (2005-03-22) 2005年3月22日(91歳没)東京都港区国籍 日本出身校東京帝国大学職業建築家受賞日本建築学会賞(1954、55、58年)RIBAゴールドメダル(1965年)AIAゴールドメダル(1966年)文化勲章(1980年)プリツカー賞(1987年)高松宮殿下記念世界文化賞(1993年)勲一等瑞宝

 

?Phyllostachys edulis Phyllostachys edulis Біологічна класифікація Домен: Ядерні (Eukaryota) Царство: Рослини (Plantae) Відділ: Streptophyta Надклас: Покритонасінні (Magnoliophyta) Клас: Однодольні (Liliopsida) Порядок: Тонконогоцвіті (Poales) Родина: Тонконогові (Poaceae) Підродина: Бамбукові (Bambusoideae) Триба: Бамбуки (Bambuseae)...

 

Thomas Meyer (2015) Thomas Meyer (* 1943 in Leipzig) ist emeritierter Professor für Politikwissenschaft an der Technischen Universität Dortmund (Schwerpunkt: Demokratietheorie, Politische Theorie, Europa). Inhaltsverzeichnis 1 Leben 2 Veröffentlichungen (Auswahl) 3 Beiträge und Artikel (Auswahl) 4 Weblinks 5 Einzelnachweise Leben Thomas Meyer studierte Philosophie, Politikwissenschaft, Psychologie und Deutsche Literatur an der Universität Frankfurt (u. a. bei Adorno, Horkheimer, Hab...

Distrik Kodagu ಕೊಡವನಾಡು, ಕೊಡಗು ಜಿಲ್ಲೆdistrikJulukan: Negara CoorgLetak distrik tersebut di KarnatakaNegaraIndiaNegara bagianKarnatakaRegionMalnadDivisiDivisi MysoreMarkas besarMadikeriTalukaMadikeri, Somwarpet, VirajpetPemerintahan • Deputi KomisionerAnurag Tewari,IAS (2013)Luas[1] • Total4.102 km2 (1,584 sq mi)Populasi (2011)[2] • Total554.519 • Kepadatan0,14/km2 (0,...

 

Calafate Estação Calafate Uso atual Estação de metrô Proprietário Governo do Estado de Minas Gerais Concessionária Metrô BH Administração Metrô BH (2022-atualidade) CBTU (1986-2022) Sistema Metrô de Belo Horizonte Linha Laranja Sigla UCL Posição Superfície Níveis 2 Plataforma Central Vias 2 Serviços Conexões Informações históricas Inauguração agosto de 1986 (37 anos) Localização Coordenadas Estação Calafate Endereço Rua Guaratã - 1052 Município  Bel...

 

Frente de Lucha Popular PalestinaOperacional 1967  [1] - presenteLiderado por Samir GhawshahObjetivos Creación de un estado palestino en los Territorios PalestinosRegiones activas Cisjordania, Franja de Gaza (Territorios Palestinos)Ideología Nacionalismo palestinoSocialismoSecularismoAliados FatahNotas 1 Escisión del Frente Popular para la Liberación de Palestina [editar datos en Wikidata] El Frente de Lucha Popular Palestina (en árabe: yabjat al-shabilla al-nidal al-filas...

This article is about an American Halloween TV film. For the quotation from Shakespeare's Macbeth, see Three Witches § Analysis. This article needs additional citations for verification. Please help improve this article by adding citations to reliable sources. Unsourced material may be challenged and removed.Find sources: Double, Double, Toil and Trouble – news · newspapers · books · scholar · JSTOR (November 2021) (Learn how and when to remove t...

 

Soquinolol Names IUPAC name 5-[3-(tert-Butylamino)-2-hydroxypropoxy]-3,4-dihydro-1H-isoquinoline-2-carbaldehyde Identifiers CAS Number 61563-18-6 Y 3D model (JSmol) Interactive imageInteractive image ChemSpider 62047 ECHA InfoCard 100.057.113 PubChem CID 68811 UNII 15CC9BOH7Q Y CompTox Dashboard (EPA) DTXSID00866865 InChI InChI=1S/C17H26N2O3/c1-17(2,3)18-9-14(21)11-22-16-6-4-5-13-10-19(12-20)8-7-15(13)16/h4-6,12,14,18,21H,7-11H2,1-3H3Key: GMJHUSJLZXFFQJ-UHFFFAOYSA-NInChI=1/C17H...

 

Non-profit organisation This article has multiple issues. Please help improve it or discuss these issues on the talk page. (Learn how and when to remove these template messages) This article needs additional citations for verification. Please help improve this article by adding citations to reliable sources. Unsourced material may be challenged and removed.Find sources: ColaLife – news · newspapers · books · scholar · JSTOR (November 2012) (Learn how a...

Thomas Boutflower Bennett (1808–14 September 1894) was an early colonist of South Australia, remembered as a schoolmaster at J. L. Young's Adelaide Educational Institution and at Saint Peter's College. He married Elizabeth (14 January 1811–11 February 1899) and with two children arrived at Holdfast Bay on the Somersetshire on 24 August 1839.[1][2][3] He started a distillery on the banks of the River Torrens at Klemzig, but was closed down by the Governor George Gre...

 

В Википедии есть статьи о других людях с фамилией Шолкович. Борис Михайлович Шолкович Дата рождения 1900 Дата смерти 1965 Страна  СССР Альма-матер Ленинградский политехнический институт Известен как конструктор теплообменников для тяжеловодных промышленных ядерных реа...

 

For the river in Prahova County, see Chiojdeanca (river). Commune in Prahova, RomaniaChiojdeancaCommuneView of Chiojdeanca Coat of armsLocation in Prahova CountyChiojdeancaLocation in RomaniaCoordinates: 45°10′N 26°16′E / 45.167°N 26.267°E / 45.167; 26.267CountryRomaniaCountyPrahovaGovernment • Mayor (2020–2024) Gheorghe Baba-Iana[1] (PSD)Area31.48 km2 (12.15 sq mi)Population (2021-12-01)[2]1,510 •...

NoxPlayer Тип Виртуализация Разработчик Nox (HongKong) Limited[1] Написана на Python Операционная система Microsoft Windows, Mac OS X Первый выпуск 6 июня 2015 Последняя версия 7.0.5.9 (28 сентября 2023; 2 месяца назад (2023-09-28)) Состояние Активно разрабатывается Лицензия Adware Сайт bignox.com  Медиафай...

 

English electronic musician and producer For other people named John Hopkins, see John Hopkins (disambiguation). Jon HopkinsHopkins in 2018 at Rockefeller Music Hall, OsloBackground informationBirth nameJonathan Julian HopkinsBorn (1979-08-15) 15 August 1979 (age 44)Kingston upon Thames, England[1]GenresElectronicaIDMambientcontemporary classicalTech houseOccupationsProducermusicianInstrumentsKeyboardorganpianoharmoniumYears active2001–presentLabelsJust MusicDominoDouble SixWeb...

 

The native form of this personal name is Woon Fong Fann. This article uses Western name order when mentioning individuals.Singaporean actress (born 1971) Fann WongFann in August 2019BornFann Woon Fong (范文芳) (1971-01-27) 27 January 1971 (age 52)SingaporeNationalitySingaporeanEducationTemasek Secondary SchoolAlma materLaSalle International Fashion SchoolOccupationsActresssingerbusinesswomanmodelYears active1988–presentAgentsHuayi BrothersCatwalk Production HouseSpouse...

Rober Bernardo III de Foix, 1276. Roger Bernardo III (? - Tarascon-sur-Ariège, 3 de marzo de 1302[1]​) fue conde de Foix y vizconde de Castellbó y de Cerdañá (Roger Bernardo II) donde sucedió a su padre Roger IV de Foix a su fallecimiento en 1265. En 1272 se alió con Geraud V conde de Armañac para combatir al discolo señor de Sompuy, el cual pidió ayuda al rey de Francia quien prohibió la guerra. Pero los aliados no hicieron caso y el rey ordenó la presencia del conde de Foix...

 

Indian film actress (born 1988) Mrunmayee DeshpandeDeshpande at the screening of NatsamratBorn (1988-05-29) 29 May 1988 (age 35)[1]Pune, Maharashtra, IndiaOccupationActressYears active2008–presentSpouse Swapnil Rao ​(m. 2016)​RelativesGautami Deshpande (sister)[2][3][4][5][6] Mrunmayee Deshpande (born 29 May 1988)[1] is an Indian actress, who appears in Bollywood and Marathi movies. She has appear...

 

Днепропетровский электровозостроительный завод Тип государственное предприятие Год основания 1934 Расположение  Украина, Днепропетровскул. Орбитальная, 13 Ключевые фигуры Нетак Борислав Борисович[1] Отрасль машиностроение Сайт devz.com.ua Электровоз постоянного тока ...

SMA Negeri 3 DenpasarInformasiDidirikan1977Jurusan atau peminatanIPA dan IPSRentang kelasX IPA, X IPS, XI IPA, XI IPS, XII IPA, XII IPSKurikulumKurikulum 2013AlamatLokasiJl. Nusa Indah 20, Denpasar, BaliSitus webwww.sman3denpasar.sch.idMoto SMA Negeri (SMAN) 3 Denpasar, merupakan salah satu Sekolah Menengah Atas Negeri yang ada di Provinsi Bali, Indonesia. Sama dengan SMA pada umumnya di Indonesia masa pendidikan sekolah di SMAN 3 Denpasar ditempuh dalam waktu tiga tahun pelajaran, mulai...

 

San Augustine redirects here. For other uses, see San Augustine (disambiguation). City in Texas, United StatesSan Augustine, TexasCityHail Blount HouseLocation of San Augustine, TexasCoordinates: 31°31′52″N 94°6′39″W / 31.53111°N 94.11083°W / 31.53111; -94.11083CountryUnited StatesStateTexasCountySan AugustineArea[1] • Total4.80 sq mi (12.44 km2) • Land4.72 sq mi (12.22 km2) • Water0....

 

Strategi Solo vs Squad di Free Fire: Cara Menang Mudah!