Это обычная практика? Почему это на самом деле сделано? Для производительности?
Да. Люди, которые делают это, обычно пытаются повторно использовать существующее программное обеспечение (которое, как вы заметили, написано на нескольких языках) или пытаются использовать несколько разных языков, для каждого из которых это хорошо.
Производительность иногда может быть связана; например, я могу захотеть использовать Lua для его быстрого создания прототипов, но подключить его к высокопроизводительному парсеру электронной почты, написанному на C.
Я думаю, что у вас будут проблемы с разными интерпретаторами / компиляторами и без проблем соединяющие разные языки. Это правда?
Иногда. Практика мультиязычности такова, что если язык будет говорить с чем-то, кроме себя, он будет говорить с C. Поэтому часто можно заставить вещи работать вместе через какой-то C-подобный интерфейс.
В противном случае первые проблемы обычно возникают либо в управлении памятью, либо на уровне виртуальных машин, которые мы могли бы рассмотреть на примере «управляемого кода». Например, очень трудно заставить программу на Haskell обмениваться объектами, выделенными в куче, с JVM. Обычно обходной путь заключается в обработке таких вызовов как удаленных вызовов процедур, как если бы программы выполнялись в разных процессах или даже на разных компьютерах. Такие вызовы могут повлечь за собой значительные накладные расходы, что часто делает невозможным совместное использование изменяемых объектов, например, для двух разных языков. Однако, если вам не нужно что-то менять, накладные расходы не так уж и плохи.
Резюме: есть веские причины использовать разные языки для решения разных задач, и было бы удивительно, если бы большая программная система не использовала несколько языков (за исключением, может быть, в одном - языковые бункеры, такие как Squeak Smalltalk, которые просто не общаются с остальным миром). Конечно, есть проблемы с совместимостью, но проблема старая, и обходные пути известны.