LINUX.ORG.RU

Red 0.6.3

 ,


4

6

Red — императивный функциональный язык программирования, представленный в 2011 году французским программистом Ненадом Ракоцевичем. Его синтаксис унаследован от интерпретируемого языка REBOL.

Цель создания Red — преодоление ограничений REBOL. По словам создателя, Red является «языком полного стека».

Red может использоваться как для высокоуровневого предметно-ориентированного программирования и создания графических интерфейсов, так и для низкоуровневого программирования операционных систем и драйверов.Его основные черты: простой синтаксис, гомоиконность, система макросов, статическая и JIT-компиляция, кросс-компиляция, малый размер исполняемых файлов (при отсутствии внешних зависимостей), REPL, возможность использовать как встраиваемый язык.

Данный релиз содержит порядка 800 исправлений и закрывает 86 задач. Одна из основных новостей — поддержка GUI под macOS с помощью нового бэкенда (что делает GUI полностью кросс-платформенным). Также можно отметить появление типа данных date!, расширения IO API, обновления LibRed.

>>> Подробности

★★★

Проверено: jollheef ()
Последнее исправление: sudopacman (всего исправлений: 4)
Ответ на: комментарий от nihirash

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

у нормальных людей всегда есть какие-то правила на тему «интероперабельности/не прибивать гвоздями»; например, емнип, в амазоне это «все ваши проги обязаны уметь общаться по сети через какой-то общеизвестный формат по вашему выбору», и в юниксе было «стандартизируйте форматы данных, а не апи»

www_linux_org_ru ★★★★★
()
Последнее исправление: www_linux_org_ru (всего исправлений: 1)
Ответ на: комментарий от nihirash

Он хочет коммон лисп, но без скобочек и кучей современных библиотек для расставления пробелов, а то сам на это не способен.

совсем не в *те* способности это дело упирается

вот, одерски с командой оказались способны наваять парсер скалы, чтобы совместить разные стили написания кода (скобки и отступы), а в результате получилось говно (по буквам: г-о-в-н-о)

вот ссылка (добрый человек запостил ее на лоре): http://www.latkin.org/blog/2017/05/02/when-the-scala-compiler-doesnt-help

я, кстати, кое-какие их синтаксические идеи сам обдумывал, но еще до написания парсера понял, что там (в моей их реализации) слишком легко получить хрупкий/двусмысленный код, и парсер писать не стал

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

сейчас изучаю твой код — от скобочек рябит в глазах; тяжело, но пока терплю

:) Я имел ввиду что скобочки не насколько часто встречаются, их необходимость сведена до минимума, можно довольно сложные конструкции умещать в одну строку без скобочек вобще.

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

1. (ты видимо это сделал) как во *время разбора* пользоваться какими-то структурами данных, которые я раньше назвал «контекст» (именно это не умеют регекспы; перл дает возможность вставлять в регекспы свой код, но это выглядит ужасно и емнип эта фича экспериментальная до сих пор)

В parse не просто можно пользоваться структурами данных, в нем (через круглые скобочки) можно вызывать обычный код на реде, а значит можно и запросы к бд делать и гуй обновлять. Кстати название «контекст» ты не зря выбрал - в реде это синоним объекта и часто используется с parse :)

2. как в язык parse (это по факту dsl) добавить свой модификатор — т.е. чтобы для конкретной новой задачи не патчить весь парсер, а воспользоваться определенным ранее модификатором, который проверяет контекст; например «мы_находимся_внутри_текста» (т.е. не внутри атрибута и не внутри кода <script>), «мы_находимся_внутри_тэга_style» — можешь придумать любой по своему вкусу или как удобнее реализовывать в рамках твоего кода

Это черезвычайно просто:

Red []

parser: context [
	state: []
	rules: [
		any [
			number! (append state 'number) |
			word!   (append state 'word)   |
			time!   (append state 'time)
		]
	]
	run: func [input] [
		state: copy []
		parse input rules
		state
	]
]

probe parser/run [1 2 3]
; [number number number]
probe parser/run [x 5 y 10:30]
; [word number word time]

loz ★★★★★
()
Последнее исправление: loz (всего исправлений: 1)

Ненужно, игрушка для одного человека и стайки примкнувших хомячков.

Вердикт: закопать, новость удалить, ТСа в бан.

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

Собственно, Facebook постепенно от него (D) отказался, построив расширение над языком OCaml - Reason, на нем теперь новые проекты и создаёт. А других крупных компаний, поддерживающих D не так много. И именно поэтому Go или Rust - куда более осмысленный выбор, так как есть большие компании, которые его используют.

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

Ты, наверное, даже это аргументировать можешь? Хорошая поддержка от огромной корпорации — минус безусловной, сам так думаю, но когда говорю это, на меня смотрят как на идиота. Помоги, подбрось аргументов.

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

Да не найдет он аргументов. Кроме как «крупная компания будет проталкивать нужные ей изменения, которые могут ухудшить язык, и с этим сообщество ничего не сможет поделать, потому что компания вкладывает бабки». Но такова жизнь.

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

а напиши тогда функцию compose

На си это будет примерно так:

#define CALL(f, x) f->fn(f, x)

typedef struct int_function {
  double (*fn)(struct int_function *, int);
} int_function;

typedef struct compose_int_functor {
  double (*fn)(struct compose_functor *, int);
  int_function *f;
  int_function *g;
} compose_int_functor ;

double compose_call(compose_int_functor *this, double x) {
  return CALL(this->f, CALL(this->g, x));
}

int_function *compose(int_function *f,
                      int_function *g) {
  compose_int_functor *result = malloc(sizeof(compose_int_functor));
  result->fn = &compose_call;
  result->f = f;
  result->g = g;
  return (int_function *)result;
}

typedef int (*function)(int);

int_function prep(function f)
{
  int_function *res = malloc(sizeof(int_function));
  res->fn = f;
  return res
}

int main()
{
  ...
  y = CALL(compose(prep(f), prep(g)), x);
}
monk ★★★★★
()
Ответ на: комментарий от batya

Шо? Одновременно? Втф?

А чего не так?
Глянь на OCaml.

мультипарадигменный: функциональный, объектно-ориентированный, императивный

Какой-то тред-детектор типа функциональщиков.

awesomelackware
()
Ответ на: комментарий от honix

главный минус Go - это то, что он разрабатывается Google corp.

Go
Автор:
Роберт Гризмер, Роб Пайк и Кен Томпсон

Дураков в списке не вижу.

awesomelackware
()
Ответ на: комментарий от matumba

То, что есть десяток маргиналов

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

Попишут, повыпендриваются пару-пяток лет, потом придут профессионалы и перепишут всё на С++

Может еще на кобол перепишут? Попробуй по-тоньше.

Тут ведь не надо забывать даже чисто человеческий фактор ЛЕНЬ

К счастью, технологии и прогресс двигают не такие люди как ты.

Вот ты вложил кучу сил в изучение Си

Я вложил много сил в Си, и обожемой, я работаю прогаммистом на Си. Есть море книг и ответов в тырнетах. Я регулярно смотрю какую-нибудь полихрень 2.0, просто потому, что интересно. А так же потому что одна из них действительно понадобится ибо будущее не за луддитами.

Думаешь, бизнесмен

Ты уж определись, про разрабов ты или про бизнесменов.

Вот когда ты сам заведёшь бизнес

«Сперва добейся»?

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

На си это будет примерно так:

нет, так это работать не будет

допустим у нас есть function fns[100] куда мы (рандомно) записываем и настоящие функции, и результат твоей compose(prep(f), prep(g)); теперь вопрос — нам fns[k](j) вызывать напрямую или через CALL(fns[k], j)?

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

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

допустим у нас есть function fns[100] куда мы (рандомно) записываем и настоящие функции, и результат твоей compose(prep(f), prep(g)); теперь вопрос — нам fns[k](j) вызывать напрямую или через CALL(fns[k], j)?

Если это function fns[100], то результат compose туда никак. Это должна быть int_function fns[100]. И тогда, естественно, CALL(fns[k], j)

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

допустим ладно, обычные функции будем засовывать в int_function fns[100] через prep

но как ты напишешь int_function compose3(int_function f, int_function g, int_function h) — но чтобы напрямую, а не через compose?

или int_function plus(int_function f, int_function g) ? так чтобы CALL( plus(prep(f), prep(f)), i ) == f(i) + g(i)

я к тому, что для этого тебе придется добавить 1 поле в твои структуры

з.ы. а еще я подозреваю, что скоро тут кто-нибудь изобретет велосипед trampolines

www_linux_org_ru ★★★★★
()
Последнее исправление: www_linux_org_ru (всего исправлений: 3)
Ответ на: комментарий от batya

Так, я образно выразился. Имеется ввиду, что на каждом языке так можно, но не на каждом нужно.

ну что, образный ты наш?

тут народ идеи подкидывает, но до приличного рабочего прототипа дело еще не дошло — видимо ты сильно недооценил ту грамотность, после которой «так можно»

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

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

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

Если это function fns[100], то результат compose туда никак. Это должна быть int_function fns[100].

c этим есть кое-какая проблема

допустим у нас есть

struct Node 
{
    int a;
    int b;
    int c;
    int d;
    int e;
    function f;
    Node* x;
    Node* y;
    Node* z;
};

и некая closed_source_function(Node *), то мы не можем вот так взять и заменить function на int_function — нам придется пересоздавать все дерево из Node-ов специально для этой функции; а если она еще и модифицирует это дерево in-place, то как быть?

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

я к тому, что для этого тебе придется добавить 1 поле в твои структуры

Никто не обещал, что будет легко. Если нужен не единичный комбинатор, а произвольные комбинаторы, то придётся использовать что-то вроде https://developer.gnome.org/gobject/2.52/gobject-Closures.html#g-closure-invoke

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

то мы не можем вот так взять и заменить function на int_function

Почему? Только не на int_function, а на int_function*. И то и то на самом деле просто указатель.

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

я к тому, что для этого тебе придется добавить 1 поле в твои структуры

На Си так часто делают. В смысле для каждого списка отдельные структуры для узлов списка.

То есть в рамках этого языка ничего плохого в

typedef struct compose3_int_functor ....

int compose3_call(compose3_int_functor *this, int x) {
  return CALL(this->f, CALL(this->g, CALL(this->h, x)));
}

int_function compose3(int_function f, int_function g, int_function h) ....

typedef struct plus_int_functor ...

я не вижу.

monk ★★★★★
()
Последнее исправление: monk (всего исправлений: 1)
Ответ на: комментарий от anonymous

анон: смотри, какой я крутой

анон: вау, да ты и правда крутой

анон: эй, не хвали себя, это не этично!

honix
()
Ответ на: комментарий от monk

Почему? Только не на int_function, а на int_function*. И то и то на самом деле просто указатель.

хорошо, заменили; и как тогда closed_source_function будет работать?

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

это я пример неудачный придумал, надо было plus только оставить

typedef struct plus_int_functor ...

int plus_call(compose3_int_functor *this, int x) {
  return CALL(this->f) + CALL(this->g);
}

int_function plus(int_function f, int_function g) ....
monk ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

как тогда closed_source_function будет работать

Если в Node.f сложная функция, то closed_source_function сможет работать с остальными полями структуры Node. Размер структуры Node не зависит от того, указывает f на функцию или на структуру.

Разумеется, если closed_source_function пытается при своей работе выполнить f, то сложную функцию туда передать нельзя (но это ограничение closed_source_function, а не языка, также как нельзя в Node.a сохранить дробное число).

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

Разумеется, если closed_source_function пытается при своей работе выполнить f, то сложную функцию туда передать нельзя (но это ограничение closed_source_function, а не языка, также как нельзя в Node.a сохранить дробное число).

facepalm.jpg

можно, и подсказка — в этом треде я уже подсказал как

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

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

Даже если создать идеальный язык (как мнили себе тщеславные создатели Go/Rust'ов), индустрия его не примет

Go очень даже приняли, насчёт раста - ещё посмотрим. Что про Swift, кстати, скажешь?

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

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

Go очень даже приняли

У Go в этом плане ситуация похожа, немного на ситуацию принца Готамы, который решил свое учение в народ пустить - очень хорошее покровительство помогло этому делу не утонуть.

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

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

А как такой язык можно охарактеризовать по сравнению с CL? С ним вводятся какие-то другие подходы к абстрагированию?

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

По мне он продвинутый CL, потому что в CL возможно программировать код, в основном через макросы, а тут это доведено до ума и есть удобные и простые средаства - parse диалект. Тот же самый пример с math:

>> 2 + 2 * 2
== 8
>> math [ 2 + 2 * 2 ]
== 6
>> source math
math: func [
    {Evaluates a block using math precedence rules, returning the last result} 
    body [block!] "Block to evaluate" 
    /safe "Returns NONE on error" 
    /local rule pos op sub end
][
    parse body: copy/deep body rule: [
        any [
            pos: ['* (op: 'multiply) | quote / (op: 'divide)] 
            [ahead sub: paren! (sub/1: math as block! sub/1) | skip] (
                end: skip pos: back pos 3 
                pos: change/only/part pos as paren! copy/part pos end end
            ) :pos 
            | into rule 
            | skip
        ]
    ] 
    either safe [attempt body] [do body]
]

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

Второе большое и важное отличие от всех языков что я видел вобще - то как вычисляются значения переменных, в Red нет скоупов от слова вобще (их можно сделать, это не сложно, кстати) и благодаря этому множесво вещей становяться проще и возможны вот такие штуки:

>> body: [a + b]
== [a + b]
>> args: [a b]
== [a b]
>> f: func args body
== func [a b][a + b]
>> f 3 5
== 8

и такие, широко используемые внутри самого языка:

>> code: [a + b]
== [a + b]
>> ctx1: context [a: 5 b: 10]
== make object! [
    a: 5
    b: 10
]
>> do bind code ctx1
== 15
>> ctx2: context [a: 10 b: -50]
== make object! [
    a: 10
    b: -50
]
>> do bind code ctx2
== -40
>> code
== [a + b]
loz ★★★★★
()
Ответ на: комментарий от nihirash

очень хорошее покровительство помогло этому делу не утонуть.

Ты ведь о гугле, так? Так у них тот же Dart есть (был) - не взлетел.

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

Думаешь, бизнесмен будет вкладывать в этот «смелый экскремент» хоть копейку?

Дык, даже на D пишут «коммерческий код» (пусть и очень мало), а уж про Go и говорить не приходится. Ты просто отстал от жизни, варишься в своём С# и мечтаешь о D и подгоняешь теории под окружение.

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

Короче, еще один язык настолько гибкий, что без поллитры изучения половины исходников не разберешься, что делает конкретный код.

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

Примерно так, код на ред как и ребол может быть супер простым и понятным, например:

run script except on [
    sundays at noon
    mondays after 10:00
    fridays before 9:30
]

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

loz ★★★★★
()
Ответ на: jtootf™ от Nefalius

о, спасибо

jtootf ★★★★★
()

Подскажите пожалуйста.

cat gui1.red

Red [Needs: 'View]
    
    view [text "Hello World!"]

./red-063 -c gui1.red

-=== Red Compiler 0.6.3 ===- 

Compiling /home/user/!/RED/EX/gui1.red ...
...using libRedRT built on 30-Aug-2017/19:34:09+3:00
...compilation time : 46 ms

Target: Linux 

Compiling to native code...
...compilation time : 1852 ms
...linking time     : 131 ms
...output file size : 39384 bytes
...output file      : /home/user/!/RED/gui1 

./gui1

*** Script Error: view has no value
*** Where: ???

Скажите в чем ошибка, что не так?

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

Неужели? Пусто у них, на #red-lan глухо. Меня он простым написанием gui и заинтересовал. Спасибо за ответ.

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