1. JavaScript / Говнокод #27623

    0

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    function* foo() {
        let i = 1;
        yield ++i;
        yield ++i;
    }
    
    function main() {
        for (const o of foo()) {
    	print(o);
        }
    
        print("done.");
    }

    вот... решил самую крутую проблему в итераторах... а ты (С/C++) так можешь?

    Запостил: ASD_77, 28 Августа 2021

    Комментарии (106) RSS

    • для любознательных - дампик тут https://pastebin.com/b2MVdqWU
      Ответить
    • ах да.. еще SEO пост - гит на говнокод тут https://github.com/ASDAlexander77/TypeScriptCompiler
      Ответить
    • и результат работы

      C:\temp>C:\dev\TypeScriptCompiler\__build\tsc\bin\tsc.exe --emit=jit -nogc C:\temp\1.ts 
      
      2
      3
      done.
      Ответить
    • в чем челендж этого кода для генерирования нативного кода - сами догадаетесь? или расказать :)?
      Ответить
      • Мне можно и рассказать. У меня опыта в этом деле, как говорят физики, абсолютный нуль, но я собираюсь в ближайшие годы заняться кое-чем интересным.
        В моём воспалённом воображении генератор - это функция, возвращающая объект, содержащий:
        - данные, нужные итератору (некое подобие замыкания, только содержит в первую очередь локальные переменные)
        - адрес якобы-функции, которую надо вызвать для продолжения (и этот адрес равен nullptr, когда генератор закончен)
        - собственно результат итерации.
        Я что-то не учёл? Или распространённые кодогенераторы так не умеют?
        Ответить
        • Насколько я понимаю, есть джва популярных способа:

          1) stackless. Здесь нам нужен контекст, в котором лежат "локалки" и какой-то маркер продолжения (число как в примерах Пи, указатель на "продолжение" как ты предложил и т.п.).

          2) stackful. Здесь мы по-хардкору аллоцируем маленький стек и переключаемся на него и обратно. Пример есть в boost::coroutine.
          Ответить
          • коньтекст это континуэйшены?
            Ответить
            • Да структурка обычная или класс.
              Ответить
              • В коко кокорутины так сделаны, угу

                Кстати очень заебись выглядит. Можно делать вид, что ты на каждый чих запускаешь отдельный процесс, и течешь
                Ответить
                • > на каждый чих запускаешь отдельный процесс, и течешь

                  Именно поэтому Снаут за эрланг.
                  Ответить
                  • Кокобляди кстати умеют его косплеить

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

                    Там кстати есть еще structural concurrency, можно управлять деревом корутин
                    И есть еще flows, это как React{Java,JS}, можно делать почти что функциональщину (всякие холодные генераторы ленивые итд)
                    Ответить
                    • > через посылки сообщений

                      – какой obj c )))
                      Ответить
                      • канальцы можно развязать, сообщения могут буферизироваться например, или тротлиться
                        Ответить
                        • > канальцы можно развязать
                          – это форум про вазэктомию?
                          Ответить
    • > решил самую крутую проблему
      > а ты (С/C++) так можешь?

      В «C» никаких проблем нет. Именно поэтому я за «C».

      Ещё в прошлом треде показали:
      #include <stdio.h>
      
      #define DECLARE() int state = 0
      
      #define BEGIN switch (state) { \
                            case 0:
      
      #define YIELD(val) do { \
                              state = __LINE__;   \
                              return val;         \
                            case __LINE__:        \
                              ;                   \
                            } while (0)
      
      #define END }
      
      int next()
      {
          static DECLARE();
          static int i=1;
          BEGIN;
              YIELD(++i);
              YIELD(++i);
          END;
          return 0;
      }
      int main()
      {
          int num;
          while (num = next()) {
              printf("%d\n", num);
          }
          printf("done\n");
          return 0;
      }


      https://ideone.com/jrswJB
      Ответить
      • запусти 2а экземпляра одновременно
        Ответить
        • > запусти 2а экземпляра одновременно

          По второму кругу? Серьёзно?

          Всё уже было в прошлом треде.
          https://ideone.com/4ZZUYA
          
          typedef struct{
              int state;	
              int i;
          }  Ctx;
          
          int fibs(Ctx* ctx)
          {
              BEGIN;
                  YIELD(++ctx->i);
                  YIELD(++ctx->i);
          
              END;
              return 0;
          } 
          
          int main()
          {
              int i=0;
          
              Ctx t0 = {0,1};
              Ctx t1 = {0,1};    
              while (i = fibs(&t0)) {
                  printf("t0:%d\n", i);
                  printf("t1:%d\n", fibs(&t1));
              } 
          
              return 0;
          }
          Ответить
          • Ну и говно
            Ответить
          • а нука залабай нам препроцессор для такого кода

            function *foo()
            {
              let i = 1;
              while (true) yield i++;
            }


            а то охото позырять как там препроцессор поживает :)
            Ответить
            • int foo(Ctx* ctx) {
                  BEGIN;
                  while (1) {
                      YIELD(ctx->i++);
                  }
                  END;
              }
              Ответить
              • как насчет такого кода?
                function *foo()
                {
                  let i = 1;
                  while (true) { yield i++; i--; }
                }
                Ответить
                • А в чем ты видишь проблему? Ну допустим
                  int foo(Ctx* ctx) {
                      BEGIN;
                      while (1) {
                          YIELD(ctx->i++);
                          ctx->i--;
                      }
                      END;
                  }
                  Ответить
                  • даю намек... замени "ctx->i--;" на printf("hello"); и скажи сколько их будет выполненно?
                    Ответить
                    • Кого "их"? Ты можешь быть более конкретным? Мне намеки не нужны
                      Ответить
                    • Сколько элементов ты вытащил из генератора, столько и будет print'ов.

                      З.Ы. Или на один меньше? Не суть.
                      Ответить
                    • Дампик для сомневающихся: https://ideone.com/mf0kF0
                      Ответить
                      • мой прокол. я забыл что С++ за вас "case" в "while" тело пихает и не материться... ну ладно... повезло вам
                        Ответить
                        • > С++ за вас "case" в "while" тело пихает и не материться

                          Ну для stackless корутин всегда нужна какая-то поддержка со стороны конпелятора. Хотя бы вот такой рудиментарный goto в середину функции.

                          А в LLVM IR разве нельзя впрыгнуть в произвольный блок (ну ок, разбив его в этой точке на джва и обмазав локалки phi'шками)?
                          Ответить
                          • там для этого надо разворачить циклы в линейный код и прыгать case .. в начало тела и конец тела... ну немного гиморойно ... т.к. тупой прыжек в центр тела не разрешен (точнее разрешен если он не портит связи) а при использовании локальных переменных это почти не реально
                            Ответить
                            • > при использовании локальных переменных это почти не реально

                              Ну я же могу воткнуть phi'шку в начале блока и показать, что локалка приходит либо из предыдущего блока либо прилетает из блока с началом свича?
                              Ответить
                              • да можно но это уже белается на уровне LLVM IR а до этого "мы" работает в хорошо вложенными структурами .. вот while не должен пересекать case switch-a
                                Ответить
                                • А, ты генераторы сразу на уровне TS раскрываешь, а дальше они уже компилятся как любой другой код?
                                  Ответить
                                  • ну да. но походу придется делать как в "С" коде .. и свои "Гото" делать - а то забадаюсь я приводить "блоки" к нужному вижу
                                    Ответить
                              • тут скорее проблема парсера TS он не разрешает пересекать "case" для других "{" "}" блоков
                                Ответить
                                • А в "TS" есть goto?
                                  Ответить
                                  • запрещенная конструкция
                                    Ответить
                                    • Лол, т.е. его добавили в язык специально чтобы запретить?
                                      Ответить
                                      • goto вообще нет в языке есть только такая конструкция
                                        lbl1: { 
                                        		print("Hello1");
                                        		break lbl1;
                                        		print("break");
                                        	}
                                        Ответить
                                        • Этот "goto" напоминает мне "goto" из "PHP": https://govnokod.ru/23798#comment400451

                                          Может тебе с такими говноограничениями лучше с "PHP" конкурировать, а не с сишкой и крестоговном?
                                          Ответить
                                          • от этого крестоговно не перестанет быть крестоговном
                                            Ответить
                                      • > его добавили в язык специально чтобы запретить?

                                        Да. Сначала в Йаже. Потом в йажаСцрипте.
                                        Ответить
                                      • > добавили в язык специально чтобы запретить?
                                        Это же любимое развлечение скриптушков

                                        Руби и перл вообще редкордсмены
                                        Ответить
                                        • Приведи реальные примеры.
                                          Ответить
                                          • В перле много чего отключает strict.

                                            Не рекомендуется юзать локальные переменные без `my`, обращаться к ключам без кавычек итд

                                            В руби рубикоп отключает много всяких фишек, ну и например рекомендует фрозен литералы (а не мутабельные)
                                            Ответить
                                • > тут скорее проблема парсера TS он не разрешает пересекать "case" для других "{" "}" блоков

                                  И опять мы приходим к тому о чём я уже говорил:

                                  > Этой конструкции сильно помогает другая ключевая особенность Сишки (которая лалками считается говном).

                                  > Возможность switch поставить case где угодно и прыгнуть вовнутрь цикла или ifа.

                                  > А в анскильных сиподобных языках, даже при использовании препроцессора, такое бы просто не сконпелировалось.


                                  https://govnokod.ru/27615#comment663353
                                  Ответить
                                  • Свитч-кейс в няшной — неструктурный оператор. Это просто удобная коллекция меток для таблицы перехода (хотя обрамление switch(){} и косит под структурное).

                                    Неструктурным был «Бейсик» до «Кубейсика» и «Фортран». Это уже потом в новомодном «Фортране-77» лалки добавили блочные операторы со словом «END», а раньше для всего были метки.

                                    В классическом «Бейсике» (до того, как лалки из «Микрософта» добавили SUB и FUNCTION) можно было оптимизировать хвостовую рекурсию, несколько GOSUB'ов могли иметь общий RETURN. Код напоминал «Ассемблер».

                                    Так может быть, есть смысл возродить «Бейсик» и «Фортран» (те самые неструктурные, с метками, ещё не испорченные лалками)?
                                    Ответить
                                    • > есть смысл возродить «Бейсик» и «Фортран»

                                      Да в общем-то ты и в няшной можешь не юзать структурные конструкции и ебашить всё через if и goto.
                                      Ответить
                                      • Тебя тогда Дейкстра обоссыт. Попросит апостола Петра и архангела Михаила отвернуться, и обоссыт
                                        Ответить
                                        • > Тебя тогда Дейкстра обоссыт

                                          Кнут обоссыт твоего Дейкстру.

                                          https://pic.plover.com/knuth-GOTO.pdf
                                          Ответить
                                          • какая лютая оцифровка, больше подходит djvu, чем pdf

                                            от такого прямо хочется найти на помойке растянутый свитер с оленями, взять старую жёлтую клавиатуру и мышь с колёсиком и накатывать на hdd mandrake linux
                                            Ответить
                                      • А gosub/return чем заменить?

                                        В принципе, в «gcc» есть «computed goto». Можно навелосипедить стек для адресов возврата...
                                        Ответить
                                        • > А gosub/return чем заменить?

                                          Ты хочешь прям как в бейсике всё одним блоком внутри main'а? Ну да, computed goto и стек.
                                          Ответить
                                          • Линус унижает анти-goto дешёвок
                                            From: Linus Torvalds
                                            Subject: Re: any chance of 2.6.0-test*?
                                            Date: 	Sun, 12 Jan 2003 11:38:35 -0800 (PST)
                                            
                                            I think goto's are fine, and they are often more readable than large
                                            amounts of indentation. That's _especially_ true if the code flow isn't
                                            actually naturally indented (in this case it is, so I don't think using
                                            goto is in any way _clearer_ than not, but in general goto's can be quite
                                            good for readability).
                                            
                                            Of course, in stupid languages like Pascal, where labels cannot be 
                                            descriptive, goto's can be bad. But that's not the fault of the goto, 
                                            that's the braindamage of the language designer.
                                            
                                            		Linus
                                            Ответить
                                            • > where labels cannot be
                                              descriptive

                                              – это о чём?
                                              Ответить
                                              • В «Паскале» тогда использовались цифровые метки (хотя они и не имели значения номеров строк, как в «Бейсике»).

                                                label 1;
                                                begin
                                                  goto 1;
                                                  Writeln('Этот текст будет пропущен');
                                                1:
                                                  Writeln('А этот будет выведен')
                                                end.
                                                Ответить
                                                • > цифровые метки

                                                  Какой багор )))

                                                  Хуже чем в дизасме.
                                                  Ответить
                                                • https://retrocomputing.stackexchange.com/questions/20369/why-does-pascal-have-numeric-labels


                                                  Essentially the label declaration is much like an EXTERNAL declaration in Assembler (or C). I guess, since goto already breaks the whole idea of structured programming, Wirth didn't care to provide a nice solution, but simply hacked his way to satisfy a few exceptions, which he may have hoped to go away :)
                                                  Ответить
                                                  • Значит, Вирт не любил goto, поэтому и не парился с реализацией меток. Просто оставил временный хак для тяжёлых случаев.
                                                    Ответить
                                                    • Вирту не нравилось goto и поэтому он сделал хуевое goto, чтобы и другим оно тоже не нравилось.
                                                      Ответить
                                                      • > он сделал хуевое goto, чтобы и другим оно тоже не нравилось

                                                        Меня ещё дико бесило, что метки надо объявлять.

                                                        И если поменял имя/номер, то надо менять объявление.
                                                        Ответить
                                                        • написано, что в самых старых версиях паскаля надо было не всегда


                                                          Unlike often assumed, the label declaration within a procedure declaration is only needed for labels that are supposed to be accessed from outside a procedure as the goto definition explains
                                                          Ответить
                                                      • goto обычное

                                                        насколько я понимаю, это было сделано для упрощения парсера

                                                        с цифры могла начинаться только метка. то есть, встретил цифру в начале лексемы, значит, это метка
                                                        Ответить
                                                        • > с цифры могла начинаться только метка. то есть, встретил цифру в начале лексемы, значит, это метка

                                                          Фак. Уже об этом сказано.

                                                          У цифровых меток есть ещё один неоспоримый плюс: возможность запилить в язык computed goto, со всеми вытекающими плюшками и баграми.
                                                          Ответить
                                                          • Это тема для срача.

                                                            С цифровыми метками можно сделать аорифметическое computed goto. С символьными computed goto тоже сделать можно, но придётся мутить со строками (больше памяти для хранения, нетривиальный инкремент).

                                                            В случае символьных меток можно запилить взятие адреса метки: label1 в правой части или @label1, чтобы было видно, что это взятие адреса. Взятие адреса цифровой метки будет выглядеть не так красиво (просто число в правой части будет неверно интерпретировано, придётся писать @1, а это тоже выглядит странно).
                                                            Ответить
                                                            • > В случае символьных меток можно запилить взятие адреса метки: label1 в правой части или @label1, чтобы было видно, что это взятие адреса

                                                              Всё верно. Но можно пойти и обратным путём.

                                                              Добавить в цифровые метки поддержку символьных алиасов.

                                                              То есть не брать адрес у метки, а наоборот разыменовывать переменную/алиас.
                                                              label1=20;
                                                              10:
                                                                ...
                                                              15:
                                                                 ...
                                                              *label1:

                                                              Особый смак что появляется возможность создания динамических плавающих меток. Но конечно возможны коллизии.
                                                              Ответить
                                                              • Переменная метка — это жесть ваще.

                                                                Напомнило шуточный ЯП с оператором COMEFROM вместо GOTO:

                                                                https://en.m.wikipedia.org/wiki/COMEFROM
                                                                Ответить
                                                                • Хехехе.

                                                                  > Переменная метка — это жесть ваще.

                                                                  Я привычно взял самый упоротый/гибкий вариант.
                                                                  Можно ограничить эти алиасы compile-time константами вроде #define LABEL 20
                                                                  Ответить
                                                          • > в язык computed goto, со всеми вытекающими плюшками и баграми.

                                                            var i:Int = parseAsInt(getUserInput());
                                                            goto i
                                                            Ответить
                                                            • > var i:Int = parseAsInt(getUserInput());
                                                              > goto i
                                                              Тут можно поучиться у брата Computed goto: Сишного switchа. Сделав default-метку как хендлер непонятных ситуаций.

                                                              Но если таковой нет, то оператор goto не срабатывает и мы просто выполняем следующую за ним строку.

                                                              Что тоже можно воспринимать как этот самый default:
                                                              Ответить
                                                              • По моему нужно просто получившееся число загружать в регистр IP. Попал не туда, ну блядь получил ошибку процессора
                                                                Ответить
                                                                • > просто получившееся число загружать в регистр IP

                                                                  ASLR и pic всё обосрут.

                                                                  Тут несколько воренатов:
                                                                  1. Считать такой goto UB.
                                                                  2. Идти как ни в чём ни бывало дальше (так ведёт себя сишный свитч когда не находит матча).
                                                                  3. Сегфолт / другое распидорашивание как у таблицы виртуальных методов
                                                                  Ответить
                                                    • > Значит, Вирт не любил goto, поэтому и не парился с реализацией меток.
                                                      > Просто оставил временный хак для тяжёлых случаев.

                                                      Не. Мне кажется тут более веская причина чем «не нравилось goto».

                                                      LL(1) грамматика.

                                                      var bagor : integer;
                                                      begin 
                                                      bagor:
                                                      Парсер грамматики в этом месте не знает что будет дальше?
                                                      { Присваивание: }
                                                      bagor:=1;
                                                      { Или метка }
                                                      bagor: Writeln('Bagor');

                                                      С цифровыми лейбами такой проблемы нет, т.к. переменная не может начинаться с цифры, а присваивание цифровой константы 2:=3 безсмысленно.
                                                      Ответить
                                                      • Именно поэтому метки в Паскале приходится объявлять, и именно поэтому они забивают глобальный неймспейс.
                                                        Ответить
                                            • А что не так в паскале? Там вроде просто объявить их надо было. А в остальном метка как метка.
                                              Ответить
                                        • у них в лишпе никаких goto и gosub нет, именно поэтому
                                          Ответить
                                      • > Да в общем-то ты и в няшной можешь не юзать структурные конструкции и ебашить всё через if и goto.

                                        Подтверждаю.

                                        No, the future isn't all that bad.

                                        If you ignore the fact that it's "structured", even 'C' programming can be appreciated by the Real Programmer: after all, there's no type checking, variable names are seven (ten? eight?) characters long.

                                        Аnd the added bonus of the Pointer data type is thrown in — like having the best parts of Fortran and assembly language in one place. (Not to mention some of the more creative uses for #define.)
                                        Ответить
                                    • > Неструктурным был «Бейсик» до «Кубейсика» и «Фортран».

                                      По-моему уже несколько раз обсуждали, что это были очень годные языки.

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

                                      Ещё разбирали что не во всех диалектах встречалось вычислимое GOTO.
                                      Ответить
                                      • > С передовой для своего времени динамической типизацией и отличным перформансом.

                                        Статической. Тип нужно было указывать либо суффиксом ($ для строк в «Бейсике»; % для целых в реализациях «Бейсика», где целые и плавающие различались), либо он определялся первой буквой идентификатора (в «Фортране» с букв I, J, K, L, M, N начинались целые; в новых «Бейсиках» для назначения типа первой букве были операторы DEFINT, DEFSTR и т. п.), либо вообще явно для каждой переменной (DIM ... AS ... в «Бейсике»).

                                        Были реализации «Бейсика» со словом REDIM, где тип можно было поменять (старая переменная уничтожалась).
                                        Ответить
                                        • > AS ... в «Бейсике»

                                          По-моему AS — новодел. У меня в интерпретаторе никакого AS не было (впервые я увидел его в QB)

                                          А была система суффиксов.

                                          DIM использовали для объявления массивов (многомерных).

                                          Отсюда и название: DIMENSION.

                                          > Статической.
                                          Затем пользователя заставляют смешать целых и плавающих питухов.
                                          Ответить
                                          • А у меня флоатов вообще не было ;(
                                            Ответить
                                            • Да, вроде на той платформе было два «Бейсика»: один с плавающими, но без графики (для ма-те-ма-ти-ков), другой с графикой, но только с целыми (для геймеров).
                                              Ответить
                                          • Ну вот с целыми и плавающими в разных реализациях было по-разному (в одном из говнокодов я даже перечислял, где именно как сделали): в одних они были смешаны, как в «Йажасцрипте», в других — разделены, но были неявные преобразования. Причём неявный каст из плавающего в целый был умным, он округлял в ближайшую сторону (2.7 он округлял до 3).
                                            Ответить
                                        • Вот не поленился, нашёл запылившийся мануал.

                                          > DEFINT, DEFSTR

                                          Этого точно не было.

                                          Зато была странная конструкция c умножением
                                          DIM A(10)
                                          DIM B$(2)*30
                                          Ответить
                                          • Это не умножение. Это ограничение на длину строки, чтобы размер элемента был фиксированным.

                                            >> DEFINT, DEFSTR

                                            > Этого точно не было.

                                            Похоже, что DEFINT, DEFSTR «Кубейсик» утащил у «Фортрана».
                                            Ответить
                                            • >Это ограничение на длину строки, чтобы размер элемента был фиксированным.

                                              Офигеть. Уже не помню такого.

                                              А в MS-диалектах такое было?
                                              Ответить
                                              • QB такого не понимает... Откуда тогда у меня это воспоминание?
                                                Ответить
                                                • > Откуда тогда у меня это воспоминание?

                                                  В «Фортране» были 2х, 4х и 8ми байтные Integerы.

                                                  INTEGER*2
                                                  INTEGER*4
                                                  INTEGER*8

                                                  Синтаксиально похоже.
                                                  Ответить
                                                  • Похоже, что несколько реализаций «Бейсика» тырили конструкции из «Фортрана».

                                                    Вполне ожидаемо, языки похожие.
                                                    Ответить
                                        • > Были реализации «Бейсика» со словом REDIM, где тип можно было поменять (старая переменная уничтожалась).

                                          Да.

                                          А в QB/VB его смысл немного поменяли: оно использовалось для изменения размеров массивов, как аналог realloc.

                                          Только если не написать With Preserve (вроде бы), то получишь массив с нулями.
                                          Ответить
                                          • Были реализации, в которых вообще все массивы были динамическими: если обращаешься к несуществующему индексу, «Бейсик» выделял дополнительную память. Но чаще вроде встречались статические массивы.
                                            Ответить
                                            • > Были реализации, в которых вообще все массивы были динамическими

                                              Удобная фигня (если с индексом не проёбывать).

                                              Её потом йажасцриптеры своровали.

                                              Но это точно было не в MS диалектах.
                                              Ответить
                                            • > если обращаешься к несуществующему индексу, «Бейсик» выделял дополнительную память

                                              Это дико удобно для сбора всякой статистики.

                                              Конечно не так идеально, как ассоциативные массивы awk.

                                              Но тем не менее не надо думать про память и пердолиться с постоянными Redim.

                                              awk я до сих пор используя для ранжирования грепов из http-логов по кодам ошибок, времени ответа, и прочему.
                                              Ответить
                                              • угу, при первом обращении там как-бы неявный ноль:) можно делать ++

                                                в перле тоже так можно, но это считается так себе практикой

                                                см autovivification
                                                Ответить
                                                • > см autovivification

                                                  Первой ссылкой статья на вики.

                                                  Мразь поражённая синдромом цыпл утёнка с упоением пишет о пёрле, руби, йаже, рнр, путухе, с#.

                                                  И ни слова об origin языках (awk, BASIC) где это было задолго до появления той анскильной параши.
                                                  Ответить
                                                  • ну может это зумер пишет)

                                                    Вообще Perl никогда не скрывал своей глубокой связи с `awk`: очень много чего он оттуда взял
                                                    Ответить
                                      • В «Фортране» из передового для той эпохи были неявные циклы (а ля форич).

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

                                        Во-вторых, неявные циклы были в операциях ввода-вывода.
                                        Ответить
                            • > т.к. тупой прыжек в центр тела не разрешен (точнее разрешен если он не портит связи)
                              > а при использовании локальных переменных это почти не реально

                              Сишка. Возможности безграничны.
                              Ответить
    • > function*

      Какой указатель )))
      Ответить
      • это не указатель - это генератор...
        Ответить
        • let foo=(a,y)=>{let g=[];for(let i=0;i<y;i++){g.push(a++)}return foo=g};
          г генератор без *
          Ответить
    • How do I crack an Amazon interview in 6 months if I have zero knowledge in coding?
      Ответить
      • ну что, никто не знает??
        Ответить
      • > amazon interview
        > zero knowledge in coding

        Устроиться на курьера или упаковщика...
        Ответить

    Добавить комментарий