Ответы пользователя по тегу Java
  • Как грамотно написать интерпретатор?

    1. Как в рантайме правильнее разграничить вызов нативных (реализованных на Java) функций и вызов функций на JavaScript (это весьма разные сущности)?

    Ну сделай разные классы для разных функций. JS динамически типизированный, так что в основном ты все равно будешь работать с каким-нибудь базовым абстрактным JsValue, от него и унаследуй классы функций. У класса JsValue сделай метод

    JsValue call(scope: JsScope, context: JsValue, args: ArrayList<JsValue>)

    который кидает TypeError: бла-бла-бла is not a function, а в классах функций (JsNativeFunction и JsFunction) переопредели его чтобы возвращал что-то.

    2. Как оптимальнее хранить scopes? Через Hashtable/HashMap в виде вектора (имитация стека) - нормальное решение?

    Я не эксперт, но я делал скоуп в виде хешмапа со ссылкой на родительский скоуп (и так по ссылкам можно было соответственно дойти до глобального скоупа), вроде нормальный вариант.

    3. Как правильно организовать поиск функций в цепочке прототипов объекта? Например, мы ищем функцию; она находится в прототипе, ссылку на который мы храним. Но при вызове такая функция должна работать с полями данных исходного объекта, а не прототипа, или прототипа прототипа и т.д. В JavaScript всё будет в такой ситуации работать корректно, а как такое грамотно эмулировать?

    Не вижу проблемы. x.foo(42) разворачивается во что-то типа этого:

    JsObject xVar = scope.getVar("x");
    xVar
        .attr("foo")    // ищет атрибут в объекте или в прототипе
        .call(scope, xVar, Arrays.asList(JsInt(42)));

    Второй параметр метода call - это и есть контекст, то есть объект у которого вызывается метод.

    4. Эффективный алгоритм разбора выражений тоже не помешал бы. Как быстро разобрать строку, зная приоритеты операторов, корректно выделить все круглые скобки, которые могут быть вложены друг в друга, и т.д. Ссылки на любую литературу, в том числе англоязычную, приветствуются.

    Тут вряд ли что-то толковое подскажу, кроме как посмотреть в сторону ANTLR и аналогов.

    P. S.
    Немного литературы по теме
    Ответ написан
  • Как привести словесный пример полиморфизма?

    Полиморфизм бывает трёх типов: параметрический, ad-hoc и полморфизм подтипов.

    Параметрический полиморфизм нужен чтобы писать логику, параметризованную типами, реализующими некоторые интерфейсы (вырожденный случай - параметризованные любыми типами). Простейший пример: функция map, применяющая функцию к каждому элементу массива. Без полиморфизма мы бы писали отдельную функцию для каждого типа:

    mapIntFloat :: (Int -> Float) -> [Int] -> [Float]
    mapIntFloat f [] = []
    mapIntFloat f (x:xs) = (f x) : (map f xs)
    
    mapIntString :: (Int -> String) -> [Int] -> [String]
    mapIntString f [] = []
    mapIntString f (x:xs) = (f x) : (map f xs)
    -- и так далее


    Выходит довольно громоздко и налицо повторение логики в каждой функции вида mapTypeType. Чтобы избежать повторения логики, параметризуем функцию map относительно типов исходного массива и массива, получаемого в результате:

    map :: forall a b. (a -> b) -> [a] -> [b]
    map f [] = []
    map f (x:xs) = (f x) : (map f xs)


    Теперь вместо конкретных типов вроде Int или Float у нас переменные типов: a и b.

    Окей, но если копнуть глубже, оказывается, что логика, похожая на map для массивов, применима и к другим типам. Например, к optional-значениям. Без ad-hoc полиморфизма мы напишем что-то типа:

    mapList :: forall a b. (a -> b) -> [a] -> [b]
    mapList f [] = []
    mapList f (x:xs) = (f x) : (mapList f xs)
    
    mapMaybe :: forall a b. (a -> b) -> Maybe a -> Maybe b
    mapMaybe f Nothing = Nothing
    mapMaybe f (Just x) = Just (f x)


    Видно, что логика везде примерно одна и та же, сигнатуры совпадают с точностью до параметризванного типа. Вот для этих случаев и нужен ad-hoc полиморфизм:

    class  Functor f  where
        map :: (a -> b) -> f a -> f b


    Мы параметризовали нужную нам логику относительно параметризованного типа f и теперь можем писать реализации для конкретных типов:

    instance  Functor Maybe  where
        map f Nothing = Nothing
        map f (Just x) = Just (f x)
    
    instance  Functor [] where
        map f [] = []
        map f (x:xs) = (f x) : (map f xs)


    Сама функция map теперь имеет тип:

    map :: forall f a b. Functor f => (a -> b) -> f a -> f b


    Теперь мы можем писать функции, которые работают с любыми функторами, то есть опять-таки сократить повторение логики в коде.

    Наконец, полиморфизм подтипов - это несколько другой подход к предыдущей проблеме. Вместо выделения общего интерфейса мы создаём базовый тип и наследуем от него остальные. В этом случае Functor будет абстрактным классом с абстрактным методом map, от которого наследуются типы Maybe, List и т.д. В таком случае сигнатура функции, принимающей и возвращающей функтор, будет выглядеть примерно так: foo :: Functor Int -> Functor String.
    Ответ написан
    1 комментарий
  • Нуборазмышления по поводу интерпретируемых Java\python\c# и компилируемых с++\с итп?

    Интерпретируемый язык - проходит 2 стадии вместо одной ( интерпретация в байт код и компиляция), компилируемый язык - 1 стадия( компиляция).


    Ох. Во-первых, не бывает интерпретируемых или компилируемых языков. Для любого языка можно написать реализацию как в виде интерпретатора, так и в виде компилятора. Во-вторых, не бывает «интерпретации в байт-код», интерпретация вообще не может быть «во что-то». Интерпретация — это непосредственно исполнение кода программы другой программой.

    На деле реализации ЯП можно поделить примерно следующим образом:

    • Трансляторы
      • Трансляторы в низкоуровневые языки (компиляторы)
        • Ahead-of-Time компиляторы (компилируют один раз, заранее)
        • Just-in-Time компиляторы (компилируют прямо во время выполнения программы, «на лету»)
      • Трансляторы в высокоуровневые языки
    • Интерпретаторы


    Так, например, GCC — статический компилятор, OpenJDK — транслятор в байт-код + JIT-компилятор байт-кода, CPython — транслятор в байт-код + интерпретатор байт-кода.

    Для языков со статической типизацией и ручным управлением памятью (C, C++, Rust etc) наиболее эффективными оказываются статические (AOT) компиляторы. Для динамических же языков со сборщиком мусора зачастую эффективнее оказывается компиляция «на лету» (just-in-time), поскольку это позволяет компилятору использовать статистику запусков для сложных оптимизаций. «Настоящие» интерпретаторы (т. е. не являющиеся на самом деле JIT-компиляторами) обычно оказываются медленнее компиляторов.

    То значит откомпилированная игра на Java, может не уступать по производительности игре написанной на с++?


    Может, если реализация на C++ низкого качества. В общем случае код на Java будет медленнее аналогичного на C++, из-за сборщика мусора и type erasure.
    Ответ написан
    Комментировать
  • Кто может проверить грамотность кода java?

    int p, q, func
    int a, b
    Что за имена?

    // End getKeys
    // End Keys
    Такие комментарии не нужны
    Ответ написан
    1 комментарий
  • Нужны ли кому то сайты написанные на Spring?

    CMS опенсорсная?
    Если нет - я бы не стал у Вас заказывать сайт на ней (если, конечно, в ней нет каких-то уникальных и нужных мне возможностей, которых нет ни в одной из топовых CMS - но это вряд ли).
    Если да - нужно кроме, собственно, разработки, всячески её продвигать - пишите статьи, записывайте видеотуториалы, пишите на какие-нибудь форумы и т. д. Если уже лежит на гитхабе, можете сюда ссылку скинуть, может, кто-нибудь заинтересуется.
    Ответ написан
    Комментировать
  • Что лучше для android?

    Нуу, если уж очень хочется странного, то с Python под андроидом вроде всё не так плохо, как с Ruby. Гуглите kivy, PyGame. Для просто запуска Python кода (не упаковки в .apk!) отлично подойдёт QPython (я так в электричке развлекаюсь)
    Ответ написан
    Комментировать