LINUX.ORG.RU

Человеческая замена C для своих задач

 ,


0

6

Хочется найти простой кроссплатформенный компилируемый язык для программирования всякой мелочи для себя. Отправной точкой можно назвать C, но хочется поменьше рутины, возможностей на ровном месте выстрелить в ногу и наличия удобных базовых структур, вроде строк, динамических массивов и прочих списков. В кандидатурах сейчас пока C++ (не хочется лезть в дебри именно плюсов, с другой стороны писать в духе C с классами кажется как-то не комильфо), Pascal (начинал с Delphi когда-то, но уже почти не помню), Vala (тыкал немного, напрягает, что надо тянуть Glib и с поддержкой + кроссплатформой не очень), Go, D (на первый взгляд тоже ситуация с поддержкой и библиотеками не радует), Rust (какой-то инопланетный, но идея с управлением памятью интересна).


Ответ на: комментарий от WDWTFWW

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

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

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

Вот именно. Иначе вопрос - из категории «хочется странного».

seiken ★★★★★
()
Ответ на: комментарий от seiken

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

Не обязательно. В D есть rdmd, специально для таких вещей: https://dlang.org/rdmd.html

eao197 ★★★★★
()
Ответ на: комментарий от eao197

Не обязательно. В D есть rdmd, специально для таких вещей: https://dlang.org/rdmd.html

Это какой-то инструмент, позволяющий писать подобия скриптов на D? Ну хорошо, вообще есть интерпретаторы C.

Мой поинт в том, что концептуально такие инструменты не делают компилируемые языки скриптовыми, т.к. все равно система типов статическая и типы надо указывать, - пусть даже если система типов их выводит автоматически в некоторых случаях, - т.е. быстро набросать скрипт, как на питоне или перле уже не получится. T.e. можно и, с одной стороны, добавлять подобные «интерпретаторы», и, с другой стороны, убирать необходимость указывать типы явно в коде, но это не сделает ЯП одинаково удобным и для скриптов, и для компилируемых наиболее эффективно в наиболее эффективный код программ.

Наиболее ярко эта противоположность скриптовости и компилируемости проявляется в Джулии. ЯП задумывался как убийца одновременно Фортрана, Матлаба, Питона, С и должен был и генерить быстрый код, и быть удобным для быстрых экспериментов на коленке с удобным отображением результатов а ля Matlab, RStudio, или хотя бы те же питоновские ноутбуки в браузере.

В итоге получился такой монстр, с динамической типизацией, компиляцией на лету через LLVM, в котором самые простейшие вещи типа показа графика прямой из 10 точек занимает чуть ли не минуту, но в то же время невозможно просто и быстро скомпилировать код в обычный бинарник без кучи дополнительных библиотек. T.e. получился одновременно и хреновый Фортран, и хреновый Питон в одном флаконе.

seiken ★★★★★
()
Ответ на: комментарий от seiken

Это какой-то инструмент, позволяющий писать подобия скриптов на D?

Это возможность запускать D-шные програмки без предварительной компиляции. Конкретно в случае D получается весьма удобно, особенно если нужно какую-то логику писать. Типы выводятся автоматически, память подчищается автоматически, ошибки типизации обнаруживает компилятор.

eao197 ★★★★★
()
Ответ на: комментарий от seiken

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

Go известен как очень быстрый компилятор. И очень легко используется в режиме скрипта:

//usr/bin/env go run $0 "$@"; exit
package main

import (
        "fmt"
        "os"
)

func main() {
        fmt.Println("Hello world!")
        cwd, _ := os.Getwd()
        fmt.Println("cwd:", cwd)
        fmt.Println("args:", os.Args[1:])
}

На компиляцию, запуск и отработку на мобильном sandy bridge уходит около 300 мс.

gag ★★★★★
()
Ответ на: комментарий от gag

На компиляцию, запуск и отработку на мобильном sandy bridge уходит около 300 мс.

И, если не ошибаюсь, уже скомпилированный исполняемый файл не будет компилироваться повторно, если исходник не изменён. Т.е. второй запуск просто вылетит в проверку last_mod двух файлов, один из которых в /tmp/ или $TMPDIR/.

kostyarin_ ★★
()
Ответ на: комментарий от kostyarin_

И, если не ошибаюсь, уже скомпилированный исполняемый файл не будет компилироваться повторно, если исходник не изменён.

Если собирать go build script.go - да. Там же запуск:

//usr/bin/env go run $0 "$@"; exit

Повторный go build у меня занимает около 110 мс, запуск и исполнение практически ничего (около 5 мс).

gag ★★★★★
()
Ответ на: комментарий от gag

Я понятия не имею о Go, но этот пример слишком короткий и примитивный, чтобы на его основе сделать адекватные выводы. И даже этот пример, скорее всего на Питоне можно сделать короче, без потери читаемости, что-то вроде 6-7 строк. А на шелле так вообще в 3.

На компиляцию, запуск и отработку на мобильном sandy bridge уходит около 300 мс.

Пример слишком маленький, чтобы судить о скорости, даже зная а приори, что у Go быстрый компилятор. Далее, для грамотного измерения как минимум нужно запускать несколько раз и указывать среднее и стандартное отклонение. Вот, у меня С'шный аналог первый раз компилируется и запускается ок. 200мс, а последующие компиляции и запуски уже в пределах 50мс. А Go на последующих запусках не опускается ниже 170мс. Означает ли это, что С в супарной производительности компиляция+выполнение в >3 раза быстрее Go. Нет, не означает (даже если это так) т.к. пример игрушечный.

seiken ★★★★★
()
Ответ на: комментарий от seiken

Tiny C Compiler

#!/usr/bin/tcc -run

#define _GNU_SOURCE // get_current_dir_name

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argc, char* argv[])
{
        printf("Hello world!\n");
        char *cur_dir_name = get_current_dir_name();
        printf("cwd: %s\n", cur_dir_name);
        printf("args:\n");
        for (int i = 1; i < argc; i++)
                printf("  %s\n", argv[i]);
        free(cur_dir_name);
        return 0;
}
Где-то 12 мс.

gcc на компиляцию тратит около 70 мс.

gag ★★★★★
()
Последнее исправление: gag (всего исправлений: 2)
Ответ на: комментарий от seiken

Далее, для грамотного измерения как минимум нужно запускать несколько раз и указывать среднее и стандартное отклонение.

Я указал среднее время на глаз после нескольких проходов (за исключением первого). Это, конечно, на так точно, но для оценки вполне сойдёт.

gag ★★★★★
()
Ответ на: комментарий от gag

Go известен как очень быстрый компилятор. И очень легко используется в режиме скрипта:

//usr/bin/env go run $0 «$@»; exit package main

import ( «fmt» «os» )

func main() { fmt.Println(«Hello world!») cwd, _ := os.Getwd() fmt.Println(«cwd:», cwd) fmt.Println(«args:», os.Args[1:]) }

На компиляцию, запуск и отработку на мобильном sandy bridge уходит около 300 мс.

Вот по-настоящему быстрый компилятор (luajit):

local lfs = require"lfs"                                                                                                                                    
print("Hello world!")                                                           
print("cwd:", lfs.currentdir())                                                 
print("args:", ...)                                                             
$ time luajit /tmp/test.lua 1 34 56
Hello world!
cwd:    /tmp
args:   1       34      56

real    0m0,002s
user    0m0,000s
sys     0m0,000s
$

На самом деле, конечно, это jit-компилятор.

anonymous
()
Ответ на: комментарий от seiken

Но ведь динамическая типизация не отменяет необходимости думать о типах. Просто ошибка в случае неправильного типа будет не на стадии компиляции, а на этапе выполнения.

andalevor ★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.